Can bindService() be made to block?

前端 未结 4 891
鱼传尺愫
鱼传尺愫 2021-02-13 15:44

I have an Android application that uses a Remote Service and I bind to it with bindService(), which is asynchronous.

The app is useless until the service is

相关标签:
4条回答
  • 2021-02-13 15:54

    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! :)

    0 讨论(0)
  • 2021-02-13 15:59

    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.

    0 讨论(0)
  • 2021-02-13 16:04

    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.

    0 讨论(0)
  • 2021-02-13 16:10

    bindService() cannot be made to block. That kind of defeats the whole purpose of a Service. You said that you whole UI consists of results from the service. I think you need to rethink your UI and populate it with some kind of intermediate representation that shows the user that the app is gathering data.

    0 讨论(0)
提交回复
热议问题