21

What would be the best way to check if an Android Service is running? I am aware of the ActivityManager API, but it seems like the use of the API is not advised for the scenarios similar to mine (source). I am also aware of the possibility of using global/persistent variables to maintain the state of a service.

I have tried to use bindService with flags set to 0, but I got the same problems as the person on the source link (the only exception was, I was trying the bindService with a local service).

The following call

getApplicationContext().bindService(new Intent(getApplicationContext(),
        MyService.class), mServiceConnection, 0);

always returns true, but does not get connected. Is this the expected behaviour? It seems to me bindService should return false if the service is not already running (it is not, I have checked that) or if the BIND_AUTO_CREATE flag is not set (again, it is not).

Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
Igor
  • 817
  • 2
  • 9
  • 21

7 Answers7

11

Use a shared preference to save service running flag.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    int res = super.onStartCommand(intent, flags, startId);
    setRunning(true);
    return res;
}

@Override
public void onDestroy() {
    super.onDestroy();
    setRunning(false);
}

private void setRunning(boolean running) {
    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
    SharedPreferences.Editor editor = pref.edit();

    editor.putBoolean(PREF_IS_RUNNING, running);
    editor.apply();
}

public static boolean isRunning(Context ctx) {
    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ctx.getApplicationContext());
    return pref.getBoolean(PREF_IS_RUNNING, false);
}
  • 11
    This is not a good idea, SharedPreferences are persisted to non-volatile storage so if for some reason the device crashes or loses power then your `onDestroy` won't be called and next time you startup your app will think the service is running even though it is not. – satur9nine Jun 26 '15 at 17:58
  • Yes, I agree. SharedPreferences are not intended for it. But, service running pref can be removed on app start. Another way: store service running bool var in Application object. – Андрей Москвичёв Jun 27 '15 at 07:46
  • onDestroy doesn't always call – Zar E Ahmer Nov 26 '16 at 14:03
  • 1
    It's better to keep a static boolean instead of it because if the user kill the app (e.g.: clear recent apps) or the device turn off unexpectedly (e.g.: low battery) the shared preference will still be true. – Erick M. Sprengel Jun 06 '17 at 17:24
11

I have the same issue; seems the best known solution is to create a public static boolean in WhateverService, set to true during onCreate (or onStartCommand, your choice) and false during onDestroy. You can then access it from any other class in the same apk. This may be racey though. There is no API within Android to check if a service is running (without side effects): See http://groups.google.com/group/android-developers/browse_thread/thread/8c4bd731681b8331/bf3ae8ef79cad75d

I suppose the race condition comes from the fact that the OS may kill a remote service (in another process) at any time. Checking a local service (same process), as suggested above, seems race-free to me -- if the OS kills the service, it kills whatever checked its status too.

bryanr
  • 126
  • 3
3

Another method:

public static boolean isServiceRunning(Context ctx, String serviceClassName) {
    ActivityManager manager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (TrackingService.class.getName().equals(serviceClassName)) {
            return true;
        }
    }
    return false;
}
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
  • When I use the above code, it gives me info of only system running services. I am looking for all services including the one which I created – user1810931 Mar 13 '13 at 18:42
1

I had the same need and found that running .bindService with something else already bound, that it would cause errors. I did this right before running .bindService

try{
    context.unbindService(fetch_connection);
} catch (IllegalArgumentException e){
    System.out.println("Unbinding didn't work. little surprise");
}
atraudes
  • 2,368
  • 2
  • 21
  • 31
0

in your activity u can simply check it by using instance of your service in my case i done it using

  button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            Intent intent=new Intent(MainActivity.this, MyService.class);
            //startService(intent);
            bindService(intent,serviceConnection,BIND_AUTO_CREATE);
            if (myService!=null)
            {
                myService.RecData(editText.getText().toString());
            }
        }
    });
}

ServiceConnection serviceConnection=new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        Toast.makeText(MainActivity.this,"onServiceConnected called",Toast.LENGTH_SHORT).show();
        MyService.MyBinder myBinder= (MyService.MyBinder) iBinder;
        myService= myBinder.getServiceInstant();
        myService.SetActivity(MainActivity.this);
        myService.RecData(editText.getText().toString());
    }
The Black Horse
  • 2,328
  • 1
  • 14
  • 21
0

See answer here:

How to check if a service is running on Android?

Community
  • 1
  • 1
Kevin Parker
  • 16,975
  • 20
  • 76
  • 105
-1

What do you plan on doing if the service is running/not running? Why not just call startService(). That will create it if it's not running, and if it is it will call its onStart() method.

Falmarri
  • 47,727
  • 41
  • 151
  • 191
  • 2
    Let's say that I would like to print a message "Service is running" or "Service is not running". That is why I have to get the information if the service is running or not. I can't do that with calling startService. – Igor Dec 14 '10 at 20:25
  • But why do you have to print this message? There are only 2 things that you can do if the service isn't running. Either start it or not. – Falmarri Dec 14 '10 at 20:28
  • 1
    Because I would like to inform the user if the service is running or not. The user should start and stop the service manually (via. a button press). When the user closes the activity (BACK button), the service should remain running. And the activity should know, when the user starts the it the next time, that the service is already running. – Igor Dec 15 '10 at 16:20
  • 2
    I think letting the user know about services is generally a bad idea. Instead, let the user know about functions. If you can't complete a function because you're not connected to a service, fail gracefully and inform the user. If you tell the user a service is running every time they run your app, that would get really annoying. They don't care if the service is running, all they want is the functionality. – Falmarri Dec 15 '10 at 16:42
  • 6
    Ok,I see I didn't give enough information here - I said the activity will print a message just to state what type of information will be needed (is service running or not) at particular time (on activity start). I didn't really mean to focus on the usability aspect, as other applications are using similar patterns (e.g. android Music player), but rather on how this could be done. So, let me rephrase my question - how does the android Music player know, when to show a 'play button' (the music player is stopped) on the activity start and when to show the 'pause button' (mp is running)? – Igor Dec 20 '10 at 08:48