iOS中后台Firestore的AddSnapshotListener

时间:2018-10-11 17:28:43

标签: c# ios firebase xamarin.forms google-cloud-firestore

我正在使用Xamarin.Forms开发适用于Android和iOS的应用程序。该应用程序需要从Firestore中提取社区列表,如果用户启用了它,则可以在每个社区中订阅警报。

在Android中,我做了一个粘性应用程序,该应用程序在启动时会启动,然后在OnStartCommand函数中,该服务使用AddSnapshotListener(this)订阅每个社区。函数(下面是示例代码)。一切正常,但是现在我需要在iOS中做同样的事情。

我进行了研究,并尝试学习iOS中的后台系统。在Microsoft的文档中,我发现iOS具有称为“提取”的后台模式,据我了解,iOSD中每隔X秒/分钟调用一次AppDelegate中的一个函数。但是,除了我将应用程序预订为类的Android之外,我无法想象如何在系统调用的函数中使用AddSnapshotListener。

那么,我该如何在iOS的后台监听Firestore集合中的更改?

一种方法可能是使用Background Fetch并调用.GetCollection(“ community1”)并检查新文档,但是问题是用户可以添加多个社区,然后可能是一个很大的互联网数据问题(另外,我认为最多需要30秒才能从Fetch Function进行回调,否则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();
    }
}

0 个答案:

没有答案