2

EDIT: I'm specifically concerned about updating my toggle in the case where the service is killed.

I have an activity which I would like to show a toggle for users to start or stop a service. The activity should show whether the service is currently running, so the activity needs to know if the service is running.

This problem has been discussed here: How to check if a service is running on Android?

With two general strategies: 1) Use the activity manager to get a list of running services: ActivityManager.getRecentTasks(). Cons: is getRecentTasks is being deprecated and is slow.

2) Use a static field in the service class to toggle state. Cons: when the service is killed the service's onDestroy() method is not called. So the static variable cannot be updated in such a scenario and the activity could believe the service is running when it is not.

Is there a way to solve this problem that is more reliable? I could re-set the static variable to a time stamp every N seconds and if the activity sees that the static variable is too old, I'd know the service had been killed. That feels icky and would have race conditions.

Community
  • 1
  • 1
Keith Carter
  • 422
  • 1
  • 6
  • 18

2 Answers2

0

I do not know if it applies to your case, but I have a service on which I created a static start method MyService.startIfNeeded(context). This method determines whether the service should be running or not depending on some internal database state. If it should be running it starts MyService using the handed context, otherwise it calls stopService to kill it (which will make a call to onDestroy() allowing the service to 'clean up').

Next onStartCommand() is called, here reading a non-static field variable isRunning to determine whether the service code should be invoked (in this case reading WiFi signal).

I imagine that a variation of this scheme might be used to get the functionality that you seek. The key for me was to make the static MyService.startIfNeeded(context) method idempotent, in the sense that if it should be running it is kept running (and not restarted), and if it should not run it is either destroyed or simply nothing happens.

Maybe it makes little sense in your situation, just wanted to throw out some ideas.

cYrixmorten
  • 7,110
  • 3
  • 25
  • 33
0

Maybe the approaches below will suit you to some extent:

  1. Broadcast-driven messaging informing activity about Service's lifecycle
  2. Recently I've come over JobScheduler example from google samples (https://github.com/googlesamples/android-JobScheduler/tree/master/Application/src/main/java/com/example/android/common/logger).

The approach here is to pass Activity's messenger to Service so that the Service can send a message with itself passed in Message.obj to Activity and thus set Activity instance as a member. At this point you can control your service lifecycle just calling your logic-bound methods straight on the Activity.

In brief: Connecting to the service: https://github.com/googlesamples/android-JobScheduler/blob/master/Application/src/main/java/com/example/android/jobscheduler/MainActivity.java (line 70 - 72)

Sending handshake message from the Service: https://github.com/googlesamples/android-JobScheduler/blob/master/Application/src/main/java/com/example/android/jobscheduler/service/TestJobService.java (line 66)

Setting Activity as a member: MainActivity, line 106 - 107

Neither of them, however, solves the problem when the Service is killed.

dawid gdanski
  • 2,432
  • 3
  • 21
  • 29