Всем привет, никак не могу сделать рабочую схему передачи данных из сервиса в Activite. Смысл такой: есть сервис, который все время слушает сообщения от SignalR, даже когда устройство заблокировано. Если пришли данные от SignalR, то сохраняем их и при выходе мобильного устройства из заблокированного состояния обновляем Activity новыми пришедшими данными. При гуглении нашел почти рабочую
схему Service+BroadCaster+ ссылка на Activity. Реализовал следующим образом:
Код сервиса
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
[Service]
public class SignalRService : Service
{
HubConnection signalRconnection;
const int NOTIFICATION_ID = 9000;
string selectedItemId = "q45514";
const string baseUrl = "http://11.11.1.111:100";
private DataReceiver mDataReceiver;
Intent mobilszDataReceiverIntent;
#region privateVar
#endregion
public override IBinder OnBind(Intent intent)
{
return (null);
}
public SignalRService()
{
}
public async override void OnStart(Intent intent, int startId)
{
await InitializeSignalRHub();
base.OnStart(intent, startId);
}
public override void OnCreate()
{
base.OnCreate();
mobilszDataReceiverIntent = new Intent("mobilszDataReceiver");
}
private async Task InitializeSignalRHub()
{
try
{
signalRconnection = new HubConnectionBuilder()
.WithUrl(baseUrl + "/broadcaster", options =>
{
})
.Build();
signalRconnection.Closed += Connection_Closed;
await ConnectToSignalRServer();
}
catch (Exception ex)
{
throw;
}
}
private async Task<bool> ConnectToSignalRServer()
{
bool connected = false;
try
{
signalRconnection.On<reportItem>("ReceiveReport", async (_reports) =>
{
string JsonReports = JsonConvert.SerializeObject(_reports);
mobilszDataReceiverIntent.PutExtra("JsonReport", JsonReports);
SendBroadcast(mobilszDataReceiverIntent);
});
await signalRconnection.StartAsync();
connected = true;
return connected;
}
catch (Exception ex)
{
Console.WriteLine($"Error {ex.Message}");
return false;
}
}
private async Task Connection_Closed(Exception arg)
{
Notification.Builder notificationBuilder = new Notification.Builder(this)
.SetContentTitle("Connection_Closed")
.SetContentText("Connection_Closed");
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(NOTIFICATION_ID, notificationBuilder.Build());
bool isConnected = false;
while (!isConnected)
{
//делаем задержку в 1 секунду
await Task.Delay(1000);
try
{
await signalRconnection.StartAsync();
isConnected = true;
return;
}
catch (Exception)
{
}
}
}
public override void OnDestroy()
{
base.OnDestroy();
UnregisterReceiver(mDataReceiver);
mDataReceiver = null;
}
}
Код BroadcastReceiver:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
[BroadcastReceiver(Enabled = true, Exported = false)]
[IntentFilter(new[] { "mobilszDataReceiver" })]
public class DataReceiver : BroadcastReceiver
{
/// <summary>
/// Последний набор данных, который посылали в ReportListActivity
/// </summary>
///
reportItem LastReportItem { get; set; }
bool IsActivityPaused;
ReportListActivity mReportListActivity;
public DataReceiver(ReportListActivity Activity)
{
mReportListActivity = Activity;
mReportListActivity.ActOnResume += MReportListActivity_ActOnResume;
mReportListActivity.ActOnPause += MReportListActivity_ActOnPause;
}
private void MReportListActivity_ActOnPause(reportItem reportItem)
{
IsActivityPaused = true;
}
private void MReportListActivity_ActOnResume(reportItem reportItem)
{
IsActivityPaused = false;
if (LastReportItem == null)
return;
if (reportItem == null || !reportItem.Equals(LastReportItem))
mReportListActivity.ReceivedSz(LastReportItem);
}
public DataReceiver()
{
}
public override void OnReceive(Context context, Intent intent)
{
reportItem deserializedReportItem = JsonConvert.DeserializeObject<reportItem>(intent.GetStringExtra("JsonReport"));
LastReportItem = deserializedReportItem;
//если новый список <reportItem> и приложение в не остановленном состоянии
if (mReportListActivity != null || !IsActivityPaused)
{
mReportListActivity.ReceivedSz(deserializedReportItem);
}
}
}
Код Activity
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
public class ReportListActivity :ListActivity
{
DataReceiver dataReceiver;
#region Events
public delegate void ReportListActivityOnResume(reportItem reportItem);
public event ReportListActivityOnResume ActOnResume;
public delegate void ReportListActivityOnPause(reportItem reportItem);
public event ReportListActivityOnPause ActOnPause;
#endregion
/// <summary>
/// Последний набор данных, который хранится в ReportListActivity
/// </summary>
///
public reportItem LastReportItem { get;private set; }
protected override async void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.reportList);
dataReceiver = new DataReceiver(this);
try
{
//SignalR service
Intent i = new Intent(this, typeof(SignalRService));
this.StartService(i);
}
catch (Exception sd)
{
throw;
}
}
public void ReceivedSz(reportItem _reports)
{
LastReportItem = _reports
RunOnUiThread(delegate
{
ListAdapter = new ReportAdapter(_reports.fltList);
FIOText.Text = _reports.driver.F;
});
}
protected override void OnResume()
{
ActOnResume?.Invoke(LastReportItem);
base.OnResume();
RegisterReceiver(dataReceiver, new IntentFilter("mobilszDataReceiver"));
}
protected override void OnPause()
{
ActOnPause?.Invoke(LastReportItem);
UnregisterReceiver(dataReceiver);
base.OnPause();
}
}
Проблема в том, что когда осуществляется вызов SendBroadcast(mobilszDataReceiverIntent);
DataReceiver пересоздается заново и соответственно ссылка на Activity теряется(вызывается пустой DataReceiver).
Как можно это проблему обойти? Спасибо