[Firestore] Add Listener for Background notification

Hi,

Right now I'm using Xamarin.Firebase.Firestore to connect to a Firestore Database. Everything works fine, but now I need to receive notifications when a specific collection has changed.
I know that in Foreground I can do it with .AddSnapshotListener, but I need to know if there is a way to do the same but in the background (so I can get a notification without having the app opened) and, if it is possible, without using an extra/external page.

Answers

  • BillyLiuBillyLiu Member, Xamarin Team Xamurai

    @JuanPZV

    In Android, you could create a service for your SnapshotListener.

  • JuanPZVJuanPZV Member ✭✭

    @BillyLiu said:
    @JuanPZV

    In Android, you could create a service for your SnapshotListener.

    Thanks for the advice. I tried to study about the Service in Android but I can't get how to link a IEventListener in a Service to work in background. Could you explain a little more the steps?

    *Note: Right now I tried to add a Service with the listener interface, but it's only works in foreground, but after I close and open the app, it's doesn't works at all

  • JuanPZVJuanPZV Member ✭✭

    Here is my code for now:

    The function to start the listener:
    public void AddCommunityAlertListener(string Community) { try { Intent serviceIntent = new Intent(MainActivity.ThisAct, typeof(BackgroundTask.CommunityAlertsListener)); serviceIntent.PutExtra("CommunityId", Community); MainActivity.ThisAct.StartService(serviceIntent); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("ACAL: " + ex.Message); } }

    The Service/Listener itself:

    `[Service]
    public class CommunityAlertsListener : Service, IEventListener
    {
    public string CommunityId = "";

        public override void OnCreate()
        {
            base.OnCreate();
            StartServiceWithNotification();
        }
    
        [return: GeneratedEnum]
        public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
        {
            string comId = intent.GetStringExtra("CommunityId");
    
            if (!string.IsNullOrWhiteSpace(comId))
            {
                CommunityId = comId;
                FirestoreService.Instance.Collection("communities").Document(CommunityId).Collection("security_events").AddSnapshotListener(this);
            } else
            {
                StopSelf();
            }
            return StartCommandResult.RedeliverIntent;
        }
    
        public override IBinder OnBind(Intent intent)
        {
            return null;
        }
    
        public void OnEvent(Java.Lang.Object value, FirebaseFirestoreException error)
        {
            if (error != null)
            {
                System.Diagnostics.Debug.WriteLine("Listen failed: " + error.Message);
                return;
            }
    
    
        }
    
        private void StartServiceWithNotification()
        {
            Intent notificationIntent = new Intent(Application.Context, typeof(MainActivity));
            //notificationIntent.SetAction();  // A string containing the action name
            notificationIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
            PendingIntent contentPendingIntent = PendingIntent.GetActivity(this, 0, notificationIntent, 0);
    
    
            Notification notification = new Android.Support.V4.App.NotificationCompat.Builder(this)
                    .SetContentTitle("Kitra")
                    .SetTicker("Kitra")
                    .SetContentText("Vigilancia")
                    .SetSmallIcon(Resource.Mipmap.icon)
                    .SetContentIntent(contentPendingIntent)
                    .SetOngoing(true)
                    .Build();
            notification.Flags = NotificationFlags.NoClear;
            StartForeground(543, notification);
        }
    }`
    

    As I said before, what I get is that the service starts when the app is opened, but after I close it, the service is being killed, even if I return RedeliverIntent or Sticky in OnStartCommand()

  • Angelru9Angelru9 ESMember ✭✭✭
    edited April 5

    @JuanPZ
    I know that your question has time, but this can help you, put this code in the service so that it opens if it is closed by the user:

        public override void OnTaskRemoved(Intent rootIntent)
        {
            Intent restartServiceIntent = new Intent(Application.Context, typeof(CommunityAlertsListener));
            restartServiceIntent.SetPackage(PackageName);
    
            PendingIntent restartServicePendingIntent = PendingIntent.GetService(Application.Context, 1, restartServiceIntent, PendingIntentFlags.OneShot);
            AlarmManager alarmService = (AlarmManager)Application.Context.GetSystemService(AlarmService);
            alarmService.Set(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime() + 10, restartServicePendingIntent);
            base.OnTaskRemoved(rootIntent);
        }
    

    Also too you should:

    return StartCommandResult.Sticky;

  • JuanPZVJuanPZV Member ✭✭

    Hi @Angelru9
    Actually the problem was that when you close the app from debugging (at least in visual studio), all the background services stops working, but if you open the app and then close it with the android's multi-task manager, the background task stills working without any problem.

    Also, due to a battery usage issue, I changed the system from local (App) to remote (Cloud), so, instead of doing the Listener in the App, I'm doing it in the Firebase Cloud Functions, and sending Push Notifications to the app.

    Thanks anyway, maybe this information will be useful to future users

  • Angelru9Angelru9 ESMember ✭✭✭
    edited April 5

    @JuanPZV

    Well, I'm working on something similar, I need my application to always listen to the sms (broadcastreceiver), even if it's closed. I do not know if I implement a service with notification or a jobscheduler.

Sign In or Register to comment.