0

I'm working in a Xamarin project that's going to track users while they are working, even if the app is closed. It's basically an app for our clients (we have an ERP) track their sellers.

For that, I've implemented a pretty simple BroadcastReceiver for starting a service (LocationService) that is going to get user's position and save it in a database or POST to some API.

The problem is that when I'm not using LocationManager, it works fine (I close the app and it keep toasting messages for example). But if I use the LocationManager the service "crash" after the app is closed and stop tracking. Am I doing something wrong? The project is fully configured for GPS tracking (it works fine when app is open or suspended).

PS: That's my first time working with Xamarin.Android. Before I've just worked with Xamarin.Forms.

Here's the LogCat. It seems to happen when AlarmManager is fired and try to get location.

Here's my code:

Start tracking

private void StartTrackingAlarm(int period)
    {
        Intent intent = new Intent(this, typeof(TrackingService));
        PendingIntent pendingIntent = PendingIntent.GetBroadcast(this, 0, intent, PendingIntentFlags.CancelCurrent);

        WriteLine($"Started tracking with period of {period} seconds.");
        AlarmManager manager = (AlarmManager)GetSystemService(AlarmService);
        manager.SetRepeating(AlarmType.RtcWakeup, SystemClock.ElapsedRealtime(), period * 1000, pendingIntent);
    }

    private void StopTrackingAlarm()
    {
        Intent intent = new Intent(this, typeof(TrackingService));
        PendingIntent pendingIntent = PendingIntent.GetBroadcast(this, 0, intent, 0);

        WriteLine($"Stopped tracking at {DateTime.Now.ToLongTimeString()} seconds.");
        AlarmManager manager = (AlarmManager)GetSystemService(AlarmService);
        manager.Cancel(pendingIntent);
    }

BroadcastReceiver

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new string[] { "android.intent.action.BOOT_COMPLETED" }, Priority = (int)IntentFilterPriority.HighPriority)]
public class TrackingService : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        Intent intentToStart = new Intent(context, typeof(LocationService));
        context.StartService(intentToStart);
    }
}

LocationService

[Service]
public class LocationService : IntentService, ILocationListener
{
    private string LogTag => $"[{nameof(LocationService)}]";
    private LocationManager LocManager { get; set; }
    private string LocationProvider { get; set; }

    protected override void OnHandleIntent(Intent intent)
    {
        Log.WriteLine(LogPriority.Debug, LogTag, $"Handling intent at {DateTime.Now.ToLongTimeString()}");
        InitializeLocationManager();

        if (LocManager.IsProviderEnabled(LocationProvider))
        {
            LocManager.RequestSingleUpdate(LocationProvider, this, null);
            Location location = LocManager.GetLastKnownLocation(LocationProvider);
            Log.WriteLine(LogPriority.Debug, LogTag, $"Last Position: [{location.Latitude}, {location.Longitude}].");
        }      
    }

    private void InitializeLocationManager()
    {
        LocManager = (LocationManager)GetSystemService(LocationService);
        Criteria criteriaForLocationService = new Criteria { Accuracy = Accuracy.Fine };
        IList<string> acceptableLocationProviders = LocManager.GetProviders(criteriaForLocationService, true);

        if (acceptableLocationProviders.Any())            
            LocationProvider = acceptableLocationProviders.First();            
        else            
            LocationProvider = string.Empty;

        Log.Debug(LogTag, $"Using {LocationProvider} at {DateTime.Now}.");
    }

    #region ILocationListener
    public void OnLocationChanged(Location location) { }

    public void OnProviderDisabled(string provider) { }

    public void OnProviderEnabled(string provider) { }

    public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras) { }
    #endregion
}
Daniel Cunha
  • 616
  • 4
  • 15
  • `Logcat` output of the app crash? (also do not post images for code or errors, add the formatted code directly to your question as text, images are not searchable/indexable/hard to see on mobile/etc....) – SushiHangover Feb 01 '19 at 19:17
  • Ok, sorry, I'm going to change it. How do I get the Logcat output? – Daniel Cunha Feb 01 '19 at 19:21
  • Logcat : https://learn.microsoft.com/en-us/xamarin/android/deploy-test/debugging/android-debug-log?tabs=windows – SushiHangover Feb 01 '19 at 19:22
  • Just added the logcat. – Daniel Cunha Feb 01 '19 at 19:39
  • 1
    You are hitting the background limitation `Not allowed to start service Intent ... app is in background` that Oreo and above implemented, see this question and its various answers on how to change your code: https://stackoverflow.com/questions/46445265/android-8-0-java-lang-illegalstateexception-not-allowed-to-start-service-inten/49846410#49846410 – SushiHangover Feb 01 '19 at 19:46
  • Works like a charm! Thank you very much for your help. – Daniel Cunha Feb 02 '19 at 11:28

0 Answers0