2

I have to implement a service were I transmit GPS (Lat/Lon) every 120 sec. to my REST backend.

I have the problem that the service seems to stop working when the screen is turned off.

  1. Attempt with a StartedService and a BroadcastReceiver
  2. Attempt with an IntentService and a WakefulBroadcastReceiver

The 1. Attempt works for example on a SAMSUNG Galaxy X COVER but not on a HUAWEI P9 Lite. Dispite the fact that I turned Power Saving mode (Power Apps) in HUAWEI phone off. So my app keeps running when screen is turned off. After e.g 10 Minutes I turned screen on on the HUAWEI phone and saw in runing services that the service is running (elapsed seconds) so I could verify that the service is not shut down.

The 2. Attempt works on no phone when screen is turned off.

Both attempts are working properly when screen is turned on (no sleep).

Note: For brevity I stripped out the code of not relevant methods (fetch/transfer gps data).

Here is the code for 1. Attempt:

Service

[Service]
public class GpsTrackerService : Service
{
    private static readonly string LogTag = "X:TruckerApp-" + typeof(GpsTrackerService).Name;
    private static readonly int NOTIFICATION_ID = 10000;
    private MobileServiceClient _mobileServiceClient;

    public TelephonyManager GetTelefonyManager()
    {
        return (Android.Telephony.TelephonyManager) GetSystemService(TelephonyService);
    }

    public bool IsRunningAsService { get; set; }


    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        Log.Debug(LogTag, "GpsTrackerService.OnStartCommand :: Service started. Timer instantiated.");
        GpsTrackerServiceUtils.SendGenericMessageToApplicationInsights("Gps-Info", LogTag, _mobileServiceClient, this, "GpsTrackerService.OnStartCommand :: Service started.Timer instantiated.");

        Task.Run(async () =>
        {
            try
            {
                await DoWork();
                await Task.Delay(TimeSpan.FromMinutes(2));
            }
            catch (Exception e)
            {
                Log.Debug(LogTag, $"GpsTrackerService.HandleTimerCallback :: (OUTER try-catch) Exception:{e.Message} Type:{e.GetType().Name}, Stacktrack:{e.StackTrace}");
                if (e.InnerException != null)
                {
                    Log.Debug(LogTag, $"GpsTrackerService.HandleTimerCallback :: (OUTER try-catch) Exception:{e.InnerException.Message} Type:{e.InnerException.GetType().Name}, Stacktrack:{e.InnerException.StackTrace}");
                }
                GpsTrackerServiceUtils.SendExceptionToApplicationInsights(e, LogTag, _mobileServiceClient, this);
            }
            finally
            {
                // Restart Service
                Intent broadcastIntent = new Intent(action: GpsConstants.GpsRestart);
                SendBroadcast(broadcastIntent);
            }

        });

        return StartCommandResult.Sticky;
    }

      public override IBinder OnBind(Intent intent)
    {
        // This is a started service, not a bound service, so we just return null.
        return null;
    }
}

BroadcastReceiver

[BroadcastReceiver(Enabled = true, Exported = true, Name = GpsConstants.GpsBroadcastReceiver, Label = "RestartServiceWhenStopped")]
[IntentFilter(new[] {GpsConstants.GpsRestart})]
public class GpsTrackerServiceBroadcastReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        try
        {
            MetricsManagerHelper.Instance.SendGenericMessageToApplicationInsights("Gps-Info", "OnReceive :: Gps Service broadcast message received. Restarting GPS Service...");
            context.StartService(new Intent(context, typeof(GpsTrackerService)));
         }
        catch (Exception e)
        {
            MetricsManagerHelper.Instance.SendExceptionToApplicationInsights(e);
        }
    }
}

Register Broadcastreceiver in MainActivity.OnCreate

 GpsTrackerServiceBroadcastReceiver = new GpsTrackerServiceBroadcastReceiver();
 RegisterReceiver(GpsTrackerServiceBroadcastReceiver, new IntentFilter(GpsConstants.GpsBroadcastReceiver));

2.Attempt

Service

[Service]
public class GpsTrackerIntentService : IntentService
{
    private static readonly string LogTag = "X:TruckerApp-" + typeof(GpsTrackerIntentService).Name;
    private static readonly int NOTIFICATION_ID = 10000;
    private MobileServiceClient _mobileServiceClient;

    public TelephonyManager GetTelefonyManager()
    {
        return (TelephonyManager) GetSystemService(TelephonyService);
    }

    protected override async void OnHandleIntent(Intent intent)
    {
        try
        {
            // perform task
            await Bootstrap();

            GpsTrackerServiceUtils.SendGenericMessageToApplicationInsightsWakeLock("Gps-Info", LogTag, _mobileServiceClient, this, "GpsTrackerService.OnHandleIntent :: Invoked.");

            await DoWork();
            await Task.Delay(TimeSpan.FromMinutes(2));
        }
        catch (Exception e)
        {
            Log.Debug(LogTag, $"GpsTrackerService.OnCreate :: Exception:{e.Message} Type:{e.GetType().Name}");
            GpsTrackerServiceUtils.SendExceptionToApplicationInsightsWakeLock(e, LogTag, _mobileServiceClient, this);
        }
        finally
        {
            WakefulBroadcastReceiver.CompleteWakefulIntent(intent);
            SendBroadcast(new Intent(this, typeof(GpsTrackerServceWakefulReceiver)));
            //var wakefulReceiverIntent = new Intent(this, typeof(GpsTrackerServceWakefulReceiver));
            //var pending = PendingIntent.GetBroadcast(this, 0, wakefulReceiverIntent, PendingIntentFlags.UpdateCurrent);
            //AlarmManager manager = (AlarmManager)GetSystemService(AlarmService);
            //manager.SetRepeating(AlarmType.RtcWakeup, SystemClock.ElapsedRealtime(), 120 * 1000, pending);
        }
    }


    public async Task DoWork()
    {
        // long running code ...
        Log.Debug(LogTag, "GpsTrackerService.HandleTimerCallback :: Invoked.");
        GpsTrackerServiceUtils.SendGenericMessageToApplicationInsightsWakeLock("Gps-Info", LogTag, _mobileServiceClient, this, "GpsTrackerService.HandleTimerCallback :: Invoked.");


    }
}

WakefulReceiver

[BroadcastReceiver]
public class GpsTrackerServceWakefulReceiver : WakefulBroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        var serviceIntent = new Intent(context, typeof(GpsTrackerIntentService));
        StartWakefulService(context, serviceIntent);
    }
}

AndroidManifest.xml

added WAKE_LOCK permission

  <uses-permission android:name="android.permission.WAKE_LOCK"/>
  <uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>

I got really desperate now. Hope someone can help me. Thanks

Eric

Erich Brunner
  • 612
  • 5
  • 19

0 Answers0