0

I have an Activity that starts a service which isn't local. Sometimes I check if is alive to perform actions.

My attempt at the moment was to use a static boolean variable. Reading some posts on SO I found out this not works because each process has it's own classloader.

Iterating over all running services is expensive to do a simple task like this.

Other solutions points out to use AIDL. In a very near future in my service, I'll store a WeakReference for the current running activity to execute it again in case of crash. Assuming for now I just want to check the service' state, is this an expensive solution too?

P.S.: I know it's an ugly solution to not handle exception properly. It's just a try.

EDIT: To clarify what I'm doing I post some code. This is the Service classs:

public class CrashRecover extends Service {

private volatile boolean stop = false;
private Thread backgroundThread;
private Messenger serviceMessenger = null;
private static boolean running = false;

...

@Override
public int onStartCommand(Intent intent, int flags, int startID){
    serviceMessenger = new Messenger(new ServiceHandler(serviceLooper));
    return START_STICKY;
}

@Override
public void onCreate(){
    super.onCreate();
    HandlerThread handlerThread = new HandlerThread("CrashRecoverThread", Process.THREAD_PRIORITY_BACKGROUND);
    handlerThread.start();

    serviceLooper = handlerThread.getLooper();
    backgroundThread = new Thread(){
        @Override
        public void run(){
            synchronized(this){
                try {
                    while(!stop){
                        sleep(500);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }                   
            }
        }
    };
    running = true;
}

@Override
public void onDestroy(){
    super.onDestroy();
    try {
        Message destroyMessage = Message.obtain();
        destroyMessage.arg1 = CrashRecover.DESTROY_SERVICE;
        serviceMessenger.send(destroyMessage);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
    running = false;
}

@Override
public IBinder onBind(Intent arg0) {
    return serviceMessenger.getBinder();
}

public static boolean isRunning(){
    return CrashRecover.running;
}

...

private class ServiceHandler extends Handler{
    public ServiceHandler(Looper looper){
        super(looper);
    }

    @Override
    public void handleMessage(Message message){
        switch(message.what){
            case REGISTER_CLIENT:
                //addActivityToRespawn(null);
                //respawnActivity();
                Log.i("INFO", "Service is registered");
                break;
            case UNREGISTER_CLIENT:
                activityParams = message.getData();
                //respawnActivity();
                if(backgroundThread.isAlive()){
                    stop = true;
                }
                Log.i("INFO", "Service is unregistered");
                break;
            case DESTROY_SERVICE:
                Log.i("INFO", "Service is destroyed");
                break;
            default:
                super.handleMessage(message);
        }
    }
}

}

And this is my class when I verify if service is running:

public class Main extends Activity {
private Button serviceButton, crashButton;
private Intent serviceIntent;
private ClientMessageHandler clientHandler;

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    clientHandler = new ClientMessageHandler();
    serviceIntent = new Intent(Main.this, CrashRecover.class);
    startService(serviceIntent);
}

...

@Override
public void onBackPressed(){
    if(CrashRecover.isRunning()){
        Log.i("INFO", "Service is running");
            //Execute some actions
    }
}
...

}

Community
  • 1
  • 1
learner
  • 1,311
  • 3
  • 18
  • 39
  • What is it you want to accomplish? Do you want to find out if the service is running? Or do you want to make sure the service is running so that you can give it something to do? If you want to use the service, how are you communicating with it? Please post some code – David Wasser Oct 16 '12 at 13:40
  • Ok, I update my post to clarify. – learner Oct 17 '12 at 01:22

1 Answers1

0

If you aren't doing this very often then I'd suggest using the "iterate over running services" method. There shouldn't be that many services running on your phone and iterating over them just accesses some internal data structures that Android keeps. Should work just fine.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Understood. In my case each new activity of my app will verify if service is alive to use it. After that, data will be send to service from time to time, lets say each 5 seconds. The loop approach aren't very effective. And AIDL is too much for use. I think I don't have many choices, AIDL maybe the solution for this. Do you agreed or not? – learner Oct 17 '12 at 14:07
  • Well, you can just call `startService()` every time you want to use the service. If it isn't running, Android will start it. If it is already running, Android will just deliver the Intent to the running service by calling `onStartCommand()`. Maybe you don't need to care if it is running or not. If you really need to know if it is running on not, you can bind to the service. If you bind to the service and the service dies/crashes or shuts down, you will get a callback `onServiceDisconnected()`. Those are your other choices. – David Wasser Oct 17 '12 at 14:45
  • I already bind to that service and I'm using Messenger to exchange messages. I'm caring for the live of the service as a means to guarantee send data to it. And a question about onServiceDisconnected(), if I've disconnected from service, the service will not send a message warning about your death(assuming it dies) because the connection was lost. I inserted a static method isRunning to guarantee this. But because they have its own classloader I can't get know if it's alive. – learner Oct 17 '12 at 15:40
  • Yes, I understand that. But if it isn't running and then you bind to it, Android will start it for you. I don't see exactly what the problem is. – David Wasser Oct 17 '12 at 15:53
  • I think I'm not clear enough. Sorry. Even bind to a service. I would like to verify each time before I send data fi it's alive. Just this. – learner Oct 17 '12 at 18:21