Android Service、Messenger进程间通信

        Android进程间通信有很多种,这里记录使用Service和Messenger来通信。在开始之前需要了解一下Android组件之Service。

       Aandroid组件使用Service有两种方式,一种是启动方式,第二种是绑定方式。因为第一种启动方式,在启动Service之后,不会得到Service的任何返回,所以对Service的控制不是很好,没有更多的交互。而第二种绑定方式,在Android绑定Service之后,Service会给调用方组件返回一个IBinder对象。这样的方式就可以进行进程间通信。

下面看服务端代码:

//服务端
public class MessengerService extends Service {
    private static final String TAG = "MessengerService";

    private static final int MESSAGE_TYPE_ONE = 1;
    private static final int MESSAGE_TYPE_TEO = 2;
    private static final int MESSAGE_TYPE_THR = 3;

    private Messenger messenger;

    public MessengerService() {
        messenger = new Messenger(new MyHandler());
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");
    }

    @Override
    public IBinder onBind(Intent intent) {
        if(intent!=null){
            Log.d(TAG, "onBind: return ok");
            return messenger.getBinder();
        }else{
            Log.d(TAG, "onBind: handler null");
            return null;
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: ");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy: ");
        super.onDestroy();
    }

    static class MyHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Messenger messenger = msg.replyTo;
            Message message = null;
            Bundle bundle = new Bundle();
            switch (msg.what){
                case MESSAGE_TYPE_ONE:{
                    message = Message.obtain(null,1);
                    bundle.putString("msg","hello one");
                    break;
                }
                case MESSAGE_TYPE_TEO:{
                    message = Message.obtain(null,2);
                    bundle.putString("msg","hello teo");
                    break;
                }
                case MESSAGE_TYPE_THR:{
                    message = Message.obtain(null,3);
                    bundle.putString("msg","hello three");
                    break;
                }
            }
            try {
                if (message!=null) {
                    message.setData(bundle);
                    messenger.send(message);
                }else {
                    Log.d(TAG, "handleMessage: message null");
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

}

      上述代码中,与平常的绑定Service方式略有不同,这里不用创建内部Binder子类,但是需要创建一个Messenger对象,onBinder方法返回的IBinder是Messenger中的IBinder。客户端接收到这个Binder之后,使用这个Binder创建一个Messenger对象,这样客户端与服务端的Messenger对象使用同一个IBinder,进程间通信就没有问题了。

      客户端代码:

  //客户端
    private void initServiceConnection(){
        Log.d(TAG, "initServiceConnection: ");
        serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mRemoteMessenger = new Messenger(service);
            }

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

    private void initMessenger(){
        Log.d(TAG, "initMessenger: ");
        messenger = new Messenger(new MyHandler());
    }

    private void bindService(){
        Log.d(TAG, "bindService: ");
        Intent intent = new Intent();
        intent.setPackage("com.junxu.servicelearn");
        intent.setAction("com.junxu.servicelearn.MyBinderService");
        bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
    }

    private void unBindService(){
        Log.d(TAG, "unBindService: ");
        unbindService(serviceConnection);
    }

    private void sendMessage(){
        Log.d(TAG, "sendMessage: ");
        try {
            Message message = Message.obtain(null,1);
            message.replyTo = messenger;
            mRemoteMessenger.send(message);
        } catch (RemoteException e) {
            Log.d(TAG, "sendMessage: "+e.getMessage());
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    static class MyHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.d(TAG, "handleMessage: "+msg.getData().getString("msg"));
        }
    }

        可以看到,客户端创建Messenger对象的时候,传入了IBinder对象,这个IBinder对象是服务器端返回来的。发送消息的时候使用的是这个Messenger对象。在客户端还创建了一个Messenger对象,这个对象创建的时候传入一个Handler对象,这个Messenger对象是传递到服务端的,供服务端回复消息的使用。从上面服务端代码可以看到,发送消息的Messenger对象是从客户端接收到的Message对象中获取的。而创建这个Messenger对象的时候传入的Handler就是用于处理服务端返回消息的。

      另一个需要注意点:客户端绑定Service的时候。使用的是隐式绑定,这里的intent不单止需要设置action还需要设置包名,否则会报错:Service Intent must be explicit: Intent。这是Android5.0之后隐式绑定Service的一个更改

 

你可能感兴趣的:(Android)