0

I want to write an application that requests data from a socket every 30-60 seconds and notify the user if there is new data.

I wrote a service but after sometime (50-60 min) Android kills the process. I'm trying to start it again in onDestroy(). The issue is when android kills the process, it does not invoke onDestroy().

What direction to look for? Read about WorkManager, it works with 15 minimum frequency.

Thanks in advance

Service

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

    public const int ServiceRunningNotifID = 9000;

    static readonly int TimerPerio = 10000;
    Timer timer;
    DateTime startTime;
    bool isStarted = false;
    INotification notification = DependencyService.Get<INotification>();     
    public ITaskService TaskService => DependencyService.Get<ITaskService>();
    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        Log.Debug(TAG, $"OnStartCommand called at {startTime}, flags={flags}, startid={startId}");             
        Notification notif = notification.ReturnNotif();
        StartForeground(ServiceRunningNotifID, notif);
 
        /*_ = DoLongRunningOperationThings()*/
        if (isStarted)
        {
            TimeSpan runtime = DateTime.UtcNow.Subtract(startTime);
            Log.Debug(TAG, $"This service was already started, it's been running for {runtime:c}.");
        }
        else
        {
            startTime = DateTime.UtcNow;
            Log.Debug(TAG, $"Starting the service, at {startTime}.");
            timer = new Timer(HandleTimerCallback, startTime, 0, TimerPerio);
            isStarted = true;
        }
        return StartCommandResult.Sticky;
    }
    string TAG = "X: ";
    void HandleTimerCallback(object state)
    {
        Location location;
        TimeSpan runTime = DateTime.UtcNow.Subtract(startTime);
        Log.Debug(TAG, $"This service has been running for {runTime:c} (since ${state}).");
        Task.Run(async () =>
        {
            // do every 30 sec. GetDataFromServer();
        });} }
Andam
  • 2,087
  • 1
  • 8
  • 21
Antoshka
  • 1
  • 1
  • I haven't worked with background services, but perhaps there is some two-step solution. Can you have a background service that wakes up occasionally, and it starts a second service that does the work every 30-60 seconds? I'm thinking if the long-running service gets to run again before the short one is killed, maybe it can "replace" the short one with a new one, thus extending its life. I have no idea whether this is possible; just brainstorming. – ToolmakerSteve Jul 23 '22 at 18:30
  • You can check this thread: [START_STICKY and START_NOT_STICKY](https://stackoverflow.com/questions/9093271/start-sticky-and-start-not-sticky/). – Jessie Zhang -MSFT Aug 02 '22 at 09:01

1 Answers1

1

Because of Android Background Execution Limits:

While an app is in the foreground, it can create and run both foreground and background services freely. When an app goes into the background, it has a window of several minutes in which it is still allowed to create and use services. At the end of that window, the app is considered to be idle. At this time, the system stops the app's background services, just as if the app had called the services' Service.stopSelf() methods.

There are two ways:

  • you can use JobScheduler and as a result your requests won't be executed at the exact time
  • you can use ForegroundService. According to doc:

Prior to Android 8.0, the usual way to create a foreground service was to create a background service, then promote that service to the foreground. With Android 8.0, there is a complication; the system doesn't allow a background app to create a background service. For this reason, Android 8.0 introduces the new method startForegroundService() to start a new service in the foreground. After the system has created the service, the app has five seconds to call the service's startForeground() method to show the new service's user-visible notification. If the app does not call startForeground() within the time limit, the system stops the service and declares the app to be ANR.

https://developer.android.com/about/versions/oreo/background#services

Hamed Goharshad
  • 631
  • 4
  • 12
  • I am starting the service StartForegroundService() private static Context context = global::Android.App.Application.Context; public void StartService() { var intent = new Intent(context, typeof(DataSource)); if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O) { context.StartForegroundService(intent); } else { context.StartService(intent); } } – Antoshka Jul 24 '22 at 19:11