How to check if a service is running on Android?

2018-12-31 02:29发布

How do I check if a background service (on Android) 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.

23条回答
春风洒进眼中
2楼-- · 2018-12-31 02:39

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.

查看更多
只若初见
3楼-- · 2018-12-31 02:39

The response of geekQ but in Kotlin class. Thanks geekQ

fun isMyServiceRunning(serviceClass : Class<*> ) : Boolean{
    var manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.name.equals(service.service.className)) {
            return true
        }
    }
    return false
}

The call

isMyServiceRunning(NewService::class.java)
查看更多
梦醉为红颜
4楼-- · 2018-12-31 02:43

I have slightly modified one of the solutions presented above, but passing the class instead of a generic string name, in order to be sure to compare strings coming out from the same method class.getName()

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

    public static boolean isServiceRunning(Context context,Class<?> serviceClass){
        final ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            Log.d(Constants.TAG, String.format("Service:%s", runningServiceInfo.service.getClassName()));
            if (runningServiceInfo.service.getClassName().equals(serviceClass.getName())){
                return true;
            }
        }
        return false;
    }
}

and then

Boolean isServiceRunning = ServiceTools.isServiceRunning(
                    MainActivity.this.getApplicationContext(),
                    BackgroundIntentService.class);
查看更多
初与友歌
5楼-- · 2018-12-31 02:43

First of all you musn't try to reach the service by using the ActivityManager. (Discussed here)

Services can run on their own, be bound to an Activity or both. The way to check in an Activity if your Service is running or not is by making an interface (that extends Binder) where you declare methods that both, the Activity and the Service, understand. You can do this by making your own Interface where you declare for example "isServiceRunning()". You can then bind your Activity to your Service, run the method isServiceRunning(), the Service will check for itself if it is running or not and returns a boolean to your Activity.

You can also use this method to stop your Service or interact with it in another way.

I used this tutorial to learn how to Implement this scenario in my application.

查看更多
余生无你
6楼-- · 2018-12-31 02:45

I just want to add a note to the answer by @Snicolas. The following steps can be used to check stop service with/without calling onDestroy().

  1. onDestroy() called: Go to Settings -> Application -> Running Services -> Select and stop your service.

  2. onDestroy() not Called: Go to Settings -> Application -> Manage Applications -> Select and "Force Stop" your application in which your service is running. However, as your application is stopped here, so definitely the service instances will also be stopped.

Finally, I would like to mention that the approach mentioned there using a static variable in singleton class is working for me.

查看更多
弹指情弦暗扣
7楼-- · 2018-12-31 02:45

If the service belongs to another process or APK use the solution based on the ActivityManager.

If you have access to its source, just use the solution based on a static field. But instead using a boolean I would suggest using a Date object. While the service is running, just update its value to 'now' and when it finishes set it to null. From the activity you can check if its null or the date is too old which will mean that it is not running.

You can also send broadcast notification from your service indicating that is running along further info like progress.

查看更多
登录 后发表回答