0

I would like to have a service (doing occasional monitoring) be active continuously. I plan to start it by listening to a BOOT_COMPLETE, which I believe makes it a "Started Service". I want a UI application to bound to it, which is working and documented. However, after the binding activity is destroyed, the Service dies because it's "unbound from all clients".

Is there a way to have a started service allow binding and still continue after the last bound services un-binds?

Returning true from onUnbind() wouldn't help, as the service should continue to be active even if no additional binder exist.

4

1 回答 1

2

在 Android 中,服务以两种方式之一启动 - 通过startService(Intent i)方法或bindService(Intent i). 用于启动服务的方法决定它是启动还是绑定。可以启动服务,然后绑定到客户端 - 或绑定然后将调用发送给它(如果已经启动,它不会重新启动)。

正如您提到的 监听,我认为这是通过对象发送BOOT_COMPLETE的 an 动作。这意味着您可以创建一个对象,并通过该方法将操作添加到该对象中。然后可以创建一个对象,该对象在接收到具有动作的意图时可以调用该方法(这是通过覆盖该方法来完成的)。IntentBroadcastIntentFilterBOOT_COMPLETEaddAction(String action)BroadcastReceiverBOOT_COMPLETEstartService(Intent i)onReceive(Context context, Intent intent)

如果您startService(Intent i)Intent收到时调用,则该服务将是已启动的服务。这意味着它只会stopService(Intent i)在应用程序调用或服务调用该stopSelf()方法时停止。它可以在运行期间被多个活动绑定和解除绑定,并且它不会停止(因为它是启动的,而不是绑定的)。

这是一个例子,使用两个Activity对象和一个Service

活动 1(您的应用的第一个活动):

    public class ServiceActivity extends Activity {   

        private IntentFilter filter = new IntentFilter();
        private BroadcastReceiver receiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();

                if(action.equals(BOOT_COMPLETE) {
                    startService(new Intent(ServiceActivity.this, MyService.class));
                }
            }
        };

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

            filter.addAction(BOOT_COMPLETE);
            registerReceiver(receiver, filter);
        }

        @Override
        protected void onStop() {
            super.onStop();
            unregisterReceiver(receiver);
        }

        //Some other code
    }

活动 2(在活动 1 之后的某个时间点使用):

    public class AnotherActivity extends Activity {   

        private MyService service;
        private ServiceConnection connection = new ServiceConnection() {

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                service = ((MyService.MyBinder)service).getService();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                service = null;
            }
        };

        @Override
        protected void onStart() {
            super.onStart();
            bindService(new Intent(this, MyService.class), connection, Context.BIND_AUTO_CREATE);
        }

        @Override
        protected void onStop() {
            super.onStop();
            unbindService(connection);
        }

        //Some other code
    }

服务:

    public class MyService extends Service {

        private MyBinder binder = new MyBinder();

        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            super.onStartCommand(intent, flags, startId);

            return START_STICKY;
        }

        //Some other code

        final class MyBinder extends Binder {
            MyService getService() {
        return MyService.this;
        }
    }

最后的笔记

为了能够将服务作为绑定使用,您需要重写该onBind(Intent intent)方法,并返回 binder 的实例MyBinder。不这样做将导致无法绑定(绑定使用getService()定义的方法设置服务变量MyBinder)。

BroadcastReceiver关闭时必须始终取消注册,Activity否则会泄漏。onStart()这就是为什么在示例中,我分别在和onStop()方法中注册和取消注册。不推荐使用onDestroy()取消注册,因为它并不总是被调用。

绑定时使用的MyService对象在关闭时也必须取消绑定Activity,因为它也可能被泄漏。onServiceDisconnected(ComponentName name)当被调用进行垃圾收集时,它被设置为 null 。

进一步阅读的来源

于 2013-06-09T14:17:36.300 回答