Xamarin.Android - Why does my location update foregroundservice crash some of the time? Crash in OnStartCommand

Niels Bergervoet - Covadis 1 Reputation point
2021-06-11T14:01:25.993+00:00

Hi everyone,

I'm making a cycling dashboard app for e-bikes and I need help figuring out why my android foreground service crashes the app for some users. The app uses a foreground service to continually update location. I'm getting reports of app crashes in this foreground service via google play console. The service is started and stopped by user interaction (that's why I chose sticky, seemed to be a good choice for this). It seems to be happening regardless of Android version, got many different reports. The crash is happening inside OnStartCommand where I have a call to StartForeground. I'm wondering if I'm allowed to use task continuations inside the OnDestroy and OnTaskRemoved methods or if that could be bad. That might be the problem somehow, but I don't know since I can't reproduce the problem. I would appreciate it if I could get some thoughts on what might be causing the crash, this is my first time implementing a foreground service.

Stack trace:

android.runtime.JavaProxyThrowable: at Rubus.Xam.Services.Droid.Implementations.BackgroundLocationService.SendLocalNotification () [0x00005] in <9e15f8b8acb6427db9f468d3d00274e2>:0
at Rubus.Xam.Services.Droid.Implementations.BackgroundLocationService.OnStartCommand (Android.Content.Intent intent, Android.App.StartCommandFlags flags, System.Int32 startId) [0x00009] in <9e15f8b8acb6427db9f468d3d00274e2>:0
at Android.App.Service.n_OnStartCommand_Landroid_content_Intent_II (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_intent, System.Int32 native_flags, System.Int32 startId) [0x0000f] in <a0916552396f4c28ac6e69de6c4f96e5>:0
at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr,int,int)
  at crc648efbf7a6358eda21.BackgroundLocationService.n_onStartCommand (Native Method)
  at crc648efbf7a6358eda21.BackgroundLocationService.onStartCommand (BackgroundLocationService.java:40)
  at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:4415)
  at android.app.ActivityThread.access$1800 (ActivityThread.java:270)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2083)
  at android.os.Handler.dispatchMessage (Handler.java:107)
  at android.os.Looper.loop (Looper.java:237)
  at android.app.ActivityThread.main (ActivityThread.java:7948)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1075)

And the offending service:

[Service]
    public class BackgroundLocationService : Service
    {
        public override IBinder OnBind(Intent intent)
        {
            return null;
        }

        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                SendLocalNotification();
            }

            StartLocationService().SafeFireAndForget((e) =>
            {
                Crashes.TrackError(e);
            }, false);

            return StartCommandResult.Sticky;
        }

        private void SendLocalNotification()
        {
            var title = App.LocalizationService["lbl_locationServiceTitle"];
            var body = App.LocalizationService["lbl_locationServiceText"];

            using var notificationBuilder = new Notification.Builder(this, MainActivity.ServiceChannelId);

            notificationBuilder.SetChannelId(MainActivity.ServiceChannelId);

            var notification = notificationBuilder
               .SetSmallIcon(Resource.Drawable.MarkerIcon)
               .SetCategory(Notification.CategoryService)
               .SetContentTitle(title)
               .SetContentText(body)
               .SetOngoing(true)
               .Build();

            StartForeground(6970, notification);
        }

        public override void OnTaskRemoved(Intent rootIntent)
        {
            StopLocationService().ContinueWith((t) =>
            {
                if (t.IsFaulted)
                {
                    Crashes.TrackError(t.Exception);
                }

                Process.KillProcess(Process.MyPid());
                StopSelf();
            }, TaskContinuationOptions.None).SafeFireAndForget((e) =>
            {
                Crashes.TrackError(e);
            });
        }

        public override void OnDestroy()
        {
            StopLocationService().ContinueWith((t) =>
            {
                if (t.IsFaulted)
                {
                    Crashes.TrackError(t.Exception);
                }

                base.OnDestroy();

            }, TaskContinuationOptions.None).SafeFireAndForget((e) => Crashes.TrackError(e));
        }

        private async Task StartLocationService()
        {
            var startResult = await App.LocationService.Start(false).ConfigureAwait(false);

            if (startResult.IsFailure)
            {
                var ex = new Exception(startResult.Error.ToString());
                Crashes.TrackError(ex);
                MessagingCenter.Send<ServiceStartFailure>(new ServiceStartFailure(ex), VanRaam.Silent.Services.Bluetooth.Location.LocationService.START_LOCATION_SERVICE_FAILURE);
            }
            else
            {
                MessagingCenter.Send<ServiceStarted>(new ServiceStarted(), VanRaam.Silent.Services.Bluetooth.Location.LocationService.LOCATION_SERVICE_STARTED);
            }
        }

        private async Task StopLocationService()
        {
            var stopResult = await App.LocationService.Stop().ConfigureAwait(false);

            if (stopResult.IsFailure)
            {
                var ex = new Exception(stopResult.Error.ToString());
                Crashes.TrackError(ex);
                MessagingCenter.Send<ServiceStopFailure>(new ServiceStopFailure(ex), VanRaam.Silent.Services.Bluetooth.Location.LocationService.LOCATION_SERVICE_STOP_FAILURE);
            }
            else
            {
                MessagingCenter.Send<ServiceStopped>(new ServiceStopped(), VanRaam.Silent.Services.Bluetooth.Location.LocationService.LOCATION_SERVICE_STOPPED);
            }
        }
    }
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,339 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.