stop - how to check service is running or not in android programmatically




How to check if a service is running on Android? (16)

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)

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.


onDestroy isn't always called in the service so this is useless!

For example: Just run the app again with one change from Eclipse. The application is forcefully exited using SIG: 9.


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.


Again, another alternative that people might find cleaner if they use pending intents (for instance with the AlarmManager:

public static boolean isRunning(Class<? extends Service> serviceClass) {
    final Intent intent = new Intent(context, serviceClass);
    return (PendingIntent.getService(context, CODE, intent, PendingIntent.FLAG_NO_CREATE) != null);
}

Where CODE is a constant that you define privately in your class to identify the pending intents associated to your service.


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.


For the use-case given here we may simply make use of the stopService() method's return value. It returns true if there exists the specified service and it is killed. Else it returns false. So you may restart the service if the result is false else it is assured that the current service has been stopped. :) It would be better if you have a look at this.


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.


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);

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.


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.


Take it easy guys... :)

I think the most suitable solution is holding a key-value pair in SharedPreferences about if the service is running or not.

Logic is very straight; at any desired position in your service class; put a boolean value which will act as a flag for you about whether the service is running or not. Then read this value whereever you want in your application.

A sample code which I am using in my app is below:

In my Service class (A service for Audio Stream), I execute the following code when the service is up;

private void updatePlayerStatus(boolean isRadioPlaying)
{
        SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putBoolean(getString(R.string.str_shared_file_radio_status_key), isRadioPlaying);
        editor.commit();
}

Then in any activity of my application, I am checking the status of the service with the help of following code;

private boolean isRadioRunning() {
        SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);

        return sharedPref.getBoolean(getString(R.string.str_shared_file_radio_status_key), false);
}

No special permissions, no loops... Easy way, clean solution :)

If you need extra information, please refer the link

Hope this helps.


The proper way to check if a service is running is to simply ask it. Implement a BroadcastReceiver in your service that responds to pings from your activities. Register the BroadcastReceiver when the service starts, and unregister it when the service is destroyed. From your activity (or any component), send a local broadcast intent to the service and if it responds, you know it's running. Note the subtle difference between ACTION_PING and ACTION_PONG in the code below.

public class PingableService extends Service
{
    public static final String ACTION_PING = PingableService.class.getName() + ".PING";
    public static final String ACTION_PONG = PingableService.class.getName() + ".PONG";

    public int onStartCommand (Intent intent, int flags, int startId)
    {
        LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(ACTION_PING));
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy ()
    {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
        super.onDestroy();
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive (Context context, Intent intent)
        {
            if (intent.getAction().equals(ACTION_PING))
            {
                LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
                manager.sendBroadcast(new Intent(ACTION_PONG));
            }
        }
    };
}


public class MyActivity extends Activity
{
    private boolean isSvcRunning = false;

    @Override
    protected void onStart()
    {
        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
        manager.registerReceiver(mReceiver, new IntentFilter(PingableService.ACTION_PONG));
        // the service will respond to this broadcast only if it's running
        manager.sendBroadcast(new Intent(PingableService.ACTION_PING));
        super.onStart();
    }

    @Override
    protected void onStop()
    {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
        super.onStop();
    }

    protected BroadcastReceiver mReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive (Context context, Intent intent)
        {
            // here you receive the response from the service
            if (intent.getAction().equals(PingableService.ACTION_PONG))
            {
                isSvcRunning = true;
            }
        }
    };
}

This applies more towards Intent Service debugging since they spawn a thread, but may work for regular services as well. I found this thread thanks to Binging

In my case, I played around with the debugger and found the thread view. It kind of looks like the bullet point icon in MS Word. Anyways, you don't have to be in debugger mode to use it. Click on the process and click on that button. Any Intent Services will show up while they are running, at least on the emulator.


This is an extract from Android docs:

Like sendBroadcast(Intent), but if there are any receivers for the Intent this function will block and immediately dispatch them before returning.

Think of this hack as "pinging" the Service since we can broadcast syncronously we can broadcast and get a result -- synchronously -- on the UI thread.

Service

@Override
public void onCreate() {
   LocalBroadcastManager
     .getInstance(this)
     .registerReceiver(new ServiceEchoReceiver(), IntentFilter("ping");
}

private class ServiceEchoReceiver{
    public void onReceive (Context context, Intent intent) {
      LocalBroadcastManager
         .getInstance(this)
         .sendBroadcastSync(new Intent("pong"));
    }
}

Activity

    bool serviceRunning = false;

    protected void onCreate (Bundle savedInstanceState){
        LocalBroadcastManager.getInstance(this).registerReceiver(pong, new IntentFilter("pong"));
        LocalBroadcastManager.getInstance(this).sendBroadcastSync(new Intent("ping"));
        if(!serviceRunning){
           //try and run the service
        }
    }

    private BroadcastReceiver pong = new BroadcastReceiver(){
        public void onReceive (Context context, Intent intent) {
          serviceRunning = true;   
        }
    }

You can use this (I didn't try this yet, but I hope this works):

if(startService(someIntent) != null) {
    Toast.makeText(getBaseContext(), "Service is already running", Toast.LENGTH_SHORT).show();
}
else {
    Toast.makeText(getBaseContext(), "There is no service running, starting service..", Toast.LENGTH_SHORT).show();
}

The startService method returns a ComponentName object if there is an already running service. If not, null will be returned.

See public abstract ComponentName startService (Intent service).

This is not like checking I think, because it's starting the service, so you can add stopService(someIntent); under the code.


    public boolean checkServiceRunning(){
         ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) 
                {
                    if ("com.example.yourpackagename.YourServiceName"
                            .equals(service.service.getClassName())) 
                    {
                        return true;
                    }
                }
             return false;
    }




android-service