Search code examples
c#androidxamarin.androidlocationforeground-service

Android Foreground Location Service stops after some time


Im using this code to get location updates for my Xamarin Android app. I have 2 questions.

  1. How to make this foreground service to run forever? I've tried to change return StartCommandResult.NotSticky; to return StartCommandResult.Sticky; and remove anything from OnDestroy() method, but OS seems to be unable to recreate service after it was killed or crashed. So, it runs about a half day only, even i've added app to my battery optimization exclude list. How to make it run forever?

  2. How to properly start service from boot? Here is what i've tried. Added following to MainActivity.cs

            [IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
            public class BootReceiver : BroadcastReceiver
            {
                public Context Context { get; set; }
                public override void OnReceive(Context context, Intent intent)
                {
                    var stepServiceIntent = new Intent(context, typeof(LocationUpdatesService));
                    stepServiceIntent.PutExtra("StartedFromBoot", true);
                    if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
                    {
                        context.StartForegroundService(stepServiceIntent);
                    }
                    else
                    {
                        context.StartService(stepServiceIntent);
                    }
                }
            }

Edited LocationUpdatesService.cs

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            Log.Info(Tag, "Service started");
            var startedFromNotification = intent.GetBooleanExtra(ExtraStartedFromNotification, false);

            var startedFromBoot = intent.GetBooleanExtra("StartedFromBoot", false);

            if (startedFromBoot)
            {
                
                //Preferences.Set("LocationUpdates", true);
                
                StartForeground(NotificationId, StartNotification("",""));
                Preferences.Set("foreground", true);

                try
                {
                    FusedLocationClient.RequestLocationUpdates(LocationRequest, LocationCallback, Looper.MyLooper());
                }
                catch (SecurityException unlikely)
                {
                    Preferences.Set("LocationUpdates", false);
                    Log.Error(Tag, "Lost location permission. Could not request updates. " + unlikely);
                }
            }
            if (startedFromNotification)
            {
                RemoveLocationUpdates();
                StopSelf();
            }
            return StartCommandResult.Sticky;
        }

I got only single location update that way right from boot. After that single update Im geting "Unknown Location" so service doesnt run continuously. So, how to properly start that service from boot to make it run continuously?

Maybe there will be a single solution for both questions, so if there is a way to start fully functional service from boot, then system could recreate it with Sticky flag and run forever.


Solution

  • Actually, the foreground service will keep running when the phone is on. But you can also use the PowerManager.WakeLock to make sure your app always keep alive even the device is sleep.

    You can check this case:Xamarin wakelock

    In addition, it seems that you want to get the user's location cyclically. So you can run a timed task in the foreground service. There are many ways to do that. Such as:

    • JobScheduler
    • AlarmManager
    • WorkManager
    • ScheduledThreadPoolExecutor

    You can check this case:Xamarin Android - Periodic task execution