I'm working on an app that takes the GPS position every minute. I tested it and it worked fine when the phone is connected to the computer. But then I took the phone off, closed it, put it in my pocket and walked around the block to see my trajectory. It turns out that the GPS points were not saved. I saw that the foreground service stops doing periodic task after being disconnected from the PC where I'm developing the app. The service starts working again when I reconnect it.
I tried a few things and I know what it's not:
1) It's not the developer mode. The problem happens when the developer mode is On and Off
2) It's not the android version. I tried 2 different android versions: 6.0 and 8.0
3) It's not the "Enable developer instrumentation (debugging and profiling)" option in the Android Options properties. I tried both ways.
4) It's not the function that I'm calling. I tried placing many different functions (non GPS related) to check if they're even being called. They're never called.
5) It's not a power saver issue. The app is unrestricted when it comes to power use, and this issue still happens when I plug the phone to a charger on a wall.
6) I tried calling the function synchronously and asynchronously. Still the same.
I have the feeling that there's a very basic thing that I'm missing. Maybe something right in front of my nose. In any case, here's the code. If you need more details please let me know.
`
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Support.V4.App;
namespace MyTest.Mobile.Droid.Services
{
[Service]
public class BackgroundService : Android.App.Service
{
static readonly string TAG = typeof(BackgroundService).FullName;
static readonly string CHANNEL_ID = "background_process";
bool isStarted;
Handler handler;
Action gpsRunnable;
public override void OnCreate()
{
base.OnCreate();
CreateNotificationChannel();
handler = new Handler();
gpsRunnable = new Action(() =>
{
// [THIS IS WHERE I PUT THE FUNCTION TO BE CALLED]
if (isStarted)
{
handler.PostDelayed(gpsRunnable, 60000);
}
});
}
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
if (intent.Action.Equals(Constants.ACTION_START_SERVICE))
{
if (!isStarted)
{
RegisterForegroundService();
handler.PostDelayed(gpsRunnable, Constants.DELAY_BETWEEN_BACKGROUND_OPERATIONS);
isStarted = true;
}
}
else if (intent.Action.Equals(Constants.ACTION_STOP_SERVICE))
{
StopForeground(true);
StopSelf();
isStarted = false;
}
return StartCommandResult.Sticky;
}
void RegisterForegroundService()
{
var notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetContentTitle(Resources.GetString(Resource.String.app_name))
.SetContentText(Resources.GetString(Resource.String.notification_text))
.SetSmallIcon(Resource.Drawable.ic_stat_name)
.SetContentIntent(BuildIntentToShowMainActivity())
.SetOngoing(true)
.Build();
StartForeground(Constants.SERVICE_RUNNING_NOTIFICATION_ID, notification);
}
PendingIntent BuildIntentToShowMainActivity()
{
var notificationIntent = new Intent(this, typeof(MainActivity));
var pendingIntent = PendingIntent.GetActivity(this, 0, notificationIntent, PendingIntentFlags.UpdateCurrent);
return pendingIntent;
}
public override void OnDestroy()
{
handler.RemoveCallbacks(gpsRunnable);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Cancel(Constants.SERVICE_RUNNING_NOTIFICATION_ID);
isStarted = false;
base.OnDestroy();
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return;
}
var name = Resources.GetString(Resource.String.channel_name);
var description = GetString(Resource.String.channel_description);
var channel = new NotificationChannel(CHANNEL_ID, name, NotificationImportance.Default)
{
Description = description
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
}
`