Forum Xamarin Xamarin.Forms

Alarm Manager SetRepeating is not working in background and app got killed

avskmkavskmk Member ✭✭
edited March 19 in Xamarin.Forms

I'm developing the location track application which tracks for every X minutes and updates to the server through API calls at a regular intervals. I started with the Foreground service which is working fine but it is draining the battery like anything. So I switched to Alarm manager set to repeat for every 15 minutes. Once the alarm got triggered, starts sending the pending tracks to API service and starts the Location track (Location Manager service).

It is working fine when the app is in foreground and not in background and app gets Killed. Some times it is working even in background. But after some time, it is not working and trigger is not firing.

Here is code to set Repeat Alarm.

    string MessageText = "Message notification";
        var date = DateTime.Now.ToString("MM'-'dd'-'yyyy");
        var time = DateTime.Now.ToString("HH:mm");
        var dateTime = date + " " + time;
        var selectedDateTime = DateTime.ParseExact(dateTime, "MM-dd-yyyy HH:mm", CultureInfo.InvariantCulture);
       if (!string.IsNullOrEmpty(MessageText))
        {
            DependencyService.Get<ILocalNotificationService>().Cancel(0);
            DependencyService.Get<ILocalNotificationService>().LocalNotification("Local Notification", MessageText, 0, selectedDateTime);
            //App.Current.MainPage.DisplayAlert("LocalNotificationDemo", "Notification details saved successfully ", "Ok");
        }
        else
        {
            //App.Current.MainPage.DisplayAlert("LocalNotificationDemo", "Please enter meassage", "OK");
        }

And the location service

    public void LocalNotification(string title, string body, int id, DateTime notifyTime)
    {

        //long repeateDay = 1000 * 60 * 60 * 24;    
        long repeateForMinute = 900000; // In milliseconds   - 15 Min
        long totalMilliSeconds = (long)(notifyTime.ToUniversalTime() - _jan1st1970).TotalMilliseconds;
        if (totalMilliSeconds < JavaSystem.CurrentTimeMillis())
        {
            totalMilliSeconds = totalMilliSeconds + repeateForMinute;
        }

        var intent = CreateIntent(id);
        var localNotification = new LocalNotification();
        localNotification.Title = title;
        localNotification.Body = body;
        localNotification.Id = id;
        localNotification.NotifyTime = notifyTime;

        if (_notificationIconId != 0)
        {
            localNotification.IconId = _notificationIconId;
        }
        else
        {
            localNotification.IconId = Resource.Drawable.abc_btn_check_material;
        }

        var serializedNotification = SerializeNotification(localNotification);
        intent.PutExtra(ScheduledAlarmHandler.LocalNotificationKey, serializedNotification);

        Random generator = new Random();
        _randomNumber = generator.Next(100000, 999999).ToString("D6");

        var pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, intent, PendingIntentFlags.Immutable);

        bool alarmUp = (PendingIntent.GetBroadcast(Application.Context, 0, new Intent("com.companyname.ready_wire"), PendingIntentFlags.NoCreate) != null);

        if (!alarmUp)
        {
            var alarmManager = GetAlarmManager();
            alarmManager.SetRepeating(AlarmType.RtcWakeup, totalMilliSeconds, repeateForMinute, pendingIntent);
        }
    }

    public void Cancel(int id)
    {
        try
        {
            var intent = CreateIntent(id);
            var pendingIntent = PendingIntent.GetBroadcast(Application.Context, Convert.ToInt32(_randomNumber), intent, PendingIntentFlags.Immutable);
            var alarmManager = GetAlarmManager();
            alarmManager.Cancel(pendingIntent);
            var notificationManager = NotificationManagerCompat.From(Application.Context);
            notificationManager.CancelAll();
            notificationManager.Cancel(id);
        }
        catch (System.Exception ex)
        { }
    }

    private Intent CreateIntent(int id)
    {

        return new Intent(Application.Context, typeof(ScheduledAlarmHandler))
            .SetAction("LocalNotifierIntent" + id);
    }

    private AlarmManager GetAlarmManager()
    {
        var alarmManager = Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
        return alarmManager;
    }

And the Broadcast Receiver is

    public override void OnReceive(Context context, Intent intent)
    {
        LocationTrackBL trackBL = new LocationTrackBL();
        trackBL.SaveServiceLog();
        trackBL.SyncPendingTracks();
    }

Saveservicelog does insert a record into table

SyncPendingTracks does make API calls to send tracks (locations). and Start the Location which triggers the following code

    private void UpdateLocation()
    {
        BindLocationRequest();

        fusedLocationProviderClient = LocationServices.GetFusedLocationProviderClient(this);
        if (ActivityCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) != Android.Content.PM.Permission.Granted)
            return;

        fusedLocationProviderClient.RequestLocationUpdates(locationRequest, GetPendingIntent());
    }

    private void BindLocationRequest()
    {
        locationRequest = new LocationRequest();
        locationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
        locationRequest.SetInterval(frequency * 60000);
        locationRequest.SetFastestInterval(frequency * 60000);
        //locationRequest.SetSmallestDisplacement(2f);
    }

    private PendingIntent GetPendingIntent()
    {
        Intent intent = new Intent(this, typeof(MyLocationService));
        intent.SetAction(MyLocationService.ACTION_PROCESS_LOCATION);
        return PendingIntent.GetBroadcast(this, 0, intent, PendingIntentFlags.UpdateCurrent);
    }

Am I doing anything wrong in my code..

one more thing, Alarm manager is working fine when it performing only Notifications

Answers

Sign In or Register to comment.