Я делаю приложение с Xamarin.Forms для Android и для iOS.Приложению необходимо извлечь список сообществ из Firestore и, если пользователь включит его, оно может подписаться на оповещения в каждом сообществе.
В Android я сделал Sticky Service, который запускается при запуске приложения,а затем в функции OnStartCommand Сервис подписывается для каждого сообщества с помощью AddSnapshotListener (this);функция (ниже пример кода).Все работает нормально, но теперь мне нужно сделать то же самое, но в iOS.
Я провел исследование и попытался изучить фоновую систему в iOS.В документации Microsoft я обнаружил, что в iOS есть фоновый режим, называемый «Fetch», и, насколько я понимаю, это функция в AppDelegate, которая вызывается iOS каждые X секунд / минут.Но вместо Android, где я подписываю приложение на класс, я не могу представить, как я могу использовать AddSnapshotListener в функции, которая вызывается из системы.
Итак, как я могу прослушивать изменения в коллекции Firestoreв фоновом режиме на iOS?
Одним из способов может быть использование Background Fetch и вызов .GetCollection ("community1") и проверка новых документов, но проблема в том, что пользователь может добавить более одного сообщества, а затемможет быть большая проблема с данными в Интернете (также я думаю, что максимум 30 секунд для обратного вызова из функции извлечения, в противном случае iOS может завершить работу приложения).
Вот код, который я используюв Android (я упростил код):
DroidCommonFunctions.cs
public void UpdateCommunityAlertListener(List<LocalCommunity> Communities)
{
if (MainActivity.ThisAct == null || Communities == null)
return;
try
{
MainActivity.ThisAct.StopService(new Intent(MainActivity.ThisAct, typeof(BackgroundTask.CommunityAlertsListener)));
if (Communities.Count == 0)
return;
Intent serviceIntent = new Intent(MainActivity.ThisAct, typeof(BackgroundTask.CommunityAlertsListener));
serviceIntent.PutExtra("CommunityLength", Communities.Count);
for (int i = 0; i < Communities.Count; i++)
{
serviceIntent.PutExtra("CommunityId" + i, Communities[i].Id);
serviceIntent.PutExtra("CommunityName" + i, Communities[i].Alias);
}
MainActivity.ThisAct.StartService(serviceIntent);
} catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("ACAL: " + ex.Message);
}
}
DroidBackgroundTask.cs
[Service]
public class CommunityAlertsListener : Service, IEventListener
{
public class CommunityRegistration
{
public string Name { get; set; } = "";
public IListenerRegistration Registration { get; set; }
}
public Dictionary<string, CommunityRegistration> CommunityDic = new Dictionary<string, CommunityRegistration>();
public override void OnCreate()
{
base.OnCreate();
StartServiceWithNotification(); //Create Android Notification
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
if(FirestoreService.Instance == null)
{
StopSelf();
return StartCommandResult.RedeliverIntent;
}
int comLength = intent.GetIntExtra("CommunityLength", 0);
for(int i = 0; i < comLength; i++)
{
string comId = intent.GetStringExtra("CommunityId" + i);
string comName = intent.GetStringExtra("CommunityName" + i);
if (string.IsNullOrWhiteSpace(comId) || string.IsNullOrWhiteSpace(comName) || CommunityDic.ContainsKey(comId))
continue;
IListenerRegistration comReg = FirestoreService.Instance.Collection("communities").Document(comId).Collection("security_events").AddSnapshotListener(this);
CommunityDic.Add(comId, new CommunityRegistration()
{
Name = comName,
Registration = comReg
});
}
if (comLength == 0 || CommunityDic.Count == 0)
StopSelf();
else
System.Diagnostics.Debug.WriteLine("CommunityAlertsListener STARTED!");
return StartCommandResult.RedeliverIntent;
}
public void OnEvent(Java.Lang.Object value, FirebaseFirestoreException error)
{
if (error != null)
{
System.Diagnostics.Debug.WriteLine("Listen failed: " + error.Message);
return;
}
try
{
QuerySnapshot snapshot = (QuerySnapshot)value;
if (snapshot.Query == null || snapshot.Query.GetType() != typeof(CollectionReference))
return;
NotifySnapshot(snapshot); //Create Android Notification
}
catch
{
System.Diagnostics.Debug.WriteLine("Listen Failed: " + error.Message);
}
}
public override void OnDestroy()
{
foreach(CommunityRegistration comReg in CommunityDic.Values)
{
try
{
if (comReg != null && comReg.Registration != null)
comReg.Registration.Remove();
} catch
{
if (comReg != null)
System.Diagnostics.Debug.WriteLine(string.Format("{0} wasn't being removed", comReg.Name));
else
System.Diagnostics.Debug.WriteLine("A community wasn't being removed");
}
}
System.Diagnostics.Debug.WriteLine("CommunityAlertsListener STOPPED!");
base.OnDestroy();
}
}