Can bindService() be made to block?

You cannot have bindService() block. However, your ServiceConnection (2nd parameter to bindService) has callbacks to tell you when the service is connected and disconnected, so you can have other code block until your onServiceConnected() method unblocks it.


When I need to wait a service to be bound before doing something else I play with locks. Precisely, the ServiceConnection owns a lock object and exposes a waitUntilConnected method that block on the lock until a wake up signal. That notification is located in the onServiceConnected callback.

public class MyServiceConnection implements ServiceConnection {

    private volatile boolean connected = false;
    private Object lock = new Object();

    @Override
    public void onServiceConnected(ComponentName name, IBinder binder) {
        connected = true;

        synchronized (lock) {
            lock.notifyAll();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        connected = false;
    }

    public void waitUntilConnected() throws InterruptedException {
        if (!connected) {
            synchronized (lock) {
                lock.wait();
            }
        }
    }

}

So, for example, if an activity has to wait a service to be bound, it calls simply the waitUntilConnected method.

protected void onStart() {
    super.onStart();

    bindService(myServiceIntent, myServiceConnection, Context.BIND_AUTO_CREATE);
    try {
        myServiceConnection.waitUntilConnected();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

I placed the waitUntilConnected method in onStart just as an example, but it has to be called in a different thread. I'd like to hear a more elegant way! :)


It seems that there is a way to do this. KeyChain.java and several Google-written classes uses a LinkedBlockingQueue to allow synchronously bind to a service.

For example, see the method called bind on this: https://github.com/android/platform_frameworks_base/blob/master/keystore/java/android/security/KeyChain.java

It seems to return the service object synchronously due to the use of blocking queue.

Unfortunately, as stated on the Android docs https://developer.android.com/reference/android/security/KeyChain.html, some methods throws InterruptedException, due to the taking of element from the queue that may be interrupted when waiting.

Tags:

Android