How to check if a service is running on Android? – Dev

The best answers to the question “How to check if a service is running on Android?” in the category Dev.

QUESTION:

How do I check if a background service is running?

I want an Android activity that toggles the state of the service — it lets me turn it on if it is off and off if it is on.

ANSWER:

I had the same problem not long ago. Since my service was local, I ended up simply using a static field in the service class to toggle state, as described by hackbod here

EDIT (for the record):

Here is the solution proposed by hackbod:

If your client and server code is part of the same .apk and you are
binding to the service with a concrete Intent (one that specifies the
exact service class), then you can simply have your service set a
global variable when it is running that your client can check.

We deliberately don’t have an API to check whether a service is
running because, nearly without fail, when you want to do something
like that you end up with race conditions in your code.

ANSWER:

I use the following from inside an activity:

private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

And I call it using:

isMyServiceRunning(MyService.class)

This works reliably, because it is based on the information about running services provided by the Android operating system through ActivityManager#getRunningServices.

All the approaches using onDestroy or onSometing events or Binders or static variables will not work reliably because as a developer you never know, when Android decides to kill your process or which of the mentioned callbacks are called or not. Please note the “killable” column in the lifecycle events table in the Android documentation.

ANSWER:

A small complement is:

My goal is to know wether a service is running without actualy running it if it is not running.

Calling bindService or calling an intent that can be caught by the service is not a good idea then as it will start the service if it is not running.

So, as miracle2k suggested, the best is to have a static field in the service class to know whether the service has been started or not.

To make it even cleaner, I suggest to transform the service in a singleton with a very very lazy fetching: that is, there is no instantiation at all of the singleton instance through static methods. The static getInstance method of your service/singleton just returns the instance of the singleton if it has been created. But it doesn’t actualy start or instanciate the singleton itself. The service is only started through normal service start methods.

It would then be even cleaner to modify the singleton design pattern to rename the confusing getInstance method into something like the isInstanceCreated() : boolean method.

The code will look like:

public class MyService extends Service
{
   private static MyService instance = null;

   public static boolean isInstanceCreated() {
      return instance != null;
   }//met

   @Override
   public void onCreate()
   {
      instance = this;
      ....
   }//met

   @Override
   public void onDestroy()
   {
      instance = null;
      ...
   }//met
}//class

This solution is elegant, but it is only relevant if you have access to the service class and only for classes iside the app/package of the service. If your classes are outside of the service app/package then you could query the ActivityManager with limitations underlined by Pieter-Jan Van Robays.

ANSWER:

Got it!

You MUST call startService() for your service to be properly registered and passing BIND_AUTO_CREATE will not suffice.

Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);

And now the ServiceTools class:

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(String serviceClassName){
        final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
                return true;
            }
        }
        return false;
     }
}