Search code examples
xamarinxamarin.androidmvvmcross

Android Service binding with MvvmCross


I am developing xamarin.Android app in MvvmCross. I want to call a service even when the App is backgrounded and a user is logged in. The problem is, I want to call this service within every say 2 hours whether the app is in foreground or background, just the user of the App needs to be logged in.

Intent loggedintent = new Intent(this,typeof(DeviceLoginHelper));
                loggedintent.PutExtra("LoggedIn", true);
                StartService(loggedintent);

I have written an android service:

 [Service]
    public class DeviceLoginHelper : IntentService
    {
        protected override void OnHandleIntent(Intent intent)
        {
            try
            {
                if(intent.HasExtra("LoggedIn"))
                {
                }
            }
            catch(Exception ex) { }
        }
    }

But how can I implement a timer? Where do I initialise and handle event to the timer. And when timer is elapsed when should I call ?

 public override void OnDestroy()
        {
            try
            {
                base.OnDestroy();
            }
            catch(Exception ex){}

        }

and when a user loges out i want to stop this service. Where do I put the call StopService() in MvvmCross


Solution

  • I would not use a Timer. Instead you should configure the AlarmManager.

    [BroadcastReceiver]
    public class AlarmReceiver : BroadcastReceiver
    {
        private static AlarmManager alarmMgr;
        private static PendingIntent alarmIntent;
        public const int NOTIFICATION_ID = 1;
        public const int IDLE_TIME_MS = 30 * 1000; // 30-seconds (update here)
        private NotificationManager mNotificationManager;
        Notification.Builder builder;
    
        public override void OnReceive(Context context, Intent intent)
        {
            // Do something when alarm triggers (here I'm building notification)
            BuildNotification(context);
    
            // reschedule alarm
            ScheduleAlarm(IDLE_TIME_MS);
        }
    
        public static Context ApplicationContext { get; set; }
        public static void ScheduleAlarm(int milliseconds)
        {
            if (milliseconds == 0) return;
    
            alarmMgr = (AlarmManager)ApplicationContext.GetSystemService(Context.AlarmService);
            var intent = new Intent(ApplicationContext, typeof(AlarmReceiver));
            alarmIntent = PendingIntent.GetBroadcast(ApplicationContext, 0, intent, 0);
    
            alarmMgr.Set(AlarmType.ElapsedRealtimeWakeup, 
                SystemClock.ElapsedRealtime() + milliseconds, alarmIntent);
        }
    
        private void BuildNotification(Context context)
        {
            mNotificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService);
    
            var contentIntent = PendingIntent.GetActivity(context, 0, new Intent(context, typeof(MainView)), 0);
            var message = $"Time is up";
            var mBuilder = new Notification.Builder(context)
                .SetAutoCancel(true)
                .SetPriority(NotificationCompat.PriorityMax)
                .SetDefaults(NotificationDefaults.All)
                .SetContentTitle("Time is up")
                .SetStyle(new Notification.BigTextStyle()
                    .BigText(message))
                .SetContentText(message)
                .SetSmallIcon(Resource.Drawable.ic_launcher);
    
            mBuilder.SetContentIntent(contentIntent);
            mNotificationManager.Notify(NOTIFICATION_ID, mBuilder.Build());
        }
    }
    

    In your startup code, simply call:

    AlarmReceiver.ApplicationContext = context;
    AlarmReceiver.ScheduleAlarm(timeInMs);