IPC之Messenger

来源:互联网 发布:mac手机铃声 编辑:程序博客网 时间:2024/05/29 03:25

我们知道Service开启的方式有俩种:
- startService
- bindService
使用startService开启服务, 一般都不和Service进行交互,
而使用bindService开启服务,一般都需要和Service进行交互,因此,如果想获取Service,并和它进行交互,请使用bindService
使用bindService有如下几种情况
-1,service和client都属于同一个process
-2, service和client属于不同的process, 给service发送消息
-3, service和client属于不同的process, 需要调用service(其实是onBind()方法返回的ibinder对象)的多个方法

第一种方式,很简单,直接创建一个内部类继承自Binder, 然后在service的onBind()方法中返回此内部类的对象
第二种方式,我们可以使用Messenger的getBinder()对象作为onBind的返回值。
第三种方式,是采取aidl方式进行通信。

今天,我们只说第二种,分析第二种的原理:
首先,创建一个service,并且在AndroidManifest.xml里面配置,并加上android:process属性

public class MessagerService extends Service {    public MessagerService() {    }    //创建一个handler    private Handler ipcHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            Log.e("LF", "msg.what : " + msg.what + ", msg.arg1 : " + msg.arg1);            Log.e("LF", "handleMessage thread : " + Thread.currentThread() + ", process : " + Process.myPid());        }    };    //使用ipcHandler构建一个Messenger对象    private Messenger messenger = new Messenger(ipcHandler);    @Override    public IBinder onBind(Intent intent) {        Log.e("LF", "onBind pid : " + Process.myPid());        //将messenger中的binder返回。        return messenger.getBinder();    }}//在manifest中的配置, 加上process属性,就表示运行在不同的进程中        <service            android:name=".MessagerService"            android:process=".remoteMessenger"            android:enabled="true"            android:exported="true">        </service>

首先来看一下Messenger messenger = new Messenger(ipcHandler); 打开Messenger的源码,通过handler构造一个Messenger, 内部只是调用handler的getIMessenger()方法,将其返回值保存在mTarget成员变量。

    public Messenger(Handler target) {        mTarget = target.getIMessenger();    }

在来看一下onBind()方法中返回的messenger.getBinder()方法在Messenger类中的定义

    public IBinder getBinder() {        //它返回的是mTarget.asBinder对象        return mTarget.asBinder();    }

通过前面构造Messenger时,我们清楚mTarget是Handler中的getIMessenger()的返回值, 我们来看一下此方法

    final IMessenger getIMessenger() {        synchronized (mQueue) {            if (mMessenger != null) {                return mMessenger;            }            mMessenger = new MessengerImpl();            return mMessenger;        }    }

从方法的定义可以看到getIMessenger()方法返回的是MessengerImpl对象,

    private final class MessengerImpl extends IMessenger.Stub {        public void send(Message msg) {            msg.sendingUid = Binder.getCallingUid();            Handler.this.sendMessage(msg);        }    }

MessengerImpl类是Handler类的内部类,它继承自IMessenger.Stub类,看到Stub,我们是不是想到了AIDL文件自动生成的内部类呀,Stub类是继承自Binder的,所以MessengerImpl是一个Binder对象。

我们也来看一下此IMessenger.java类

public interface IMessenger extends android.os.IInterface{    public static abstract class Stub extends android.os.Binder implements android.os.IMessenger {        ......        public Stub()        {            this.attachInterface(this, DESCRIPTOR);        }        public static android.os.IMessenger asInterface(android.os.IBinder obj) {            if ((obj==null)) {                return null;            }            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            if (((iin!=null)&&(iin instanceof android.os.IMessenger))) {                return ((android.os.IMessenger)iin);}            return new android.os.IMessenger.Stub.Proxy(obj);        }        @Override public android.os.IBinder asBinder() {            return this;        }    ......

和我们自己创建的aidl文件之后,系统给我们自动生成的一模一样, 因此我们在onBind()方法中返回的mTarget.asBinder() ,就等于handler.getIMessenger().asBinder() ,最后其实就是MessengerImpl, 它是Stub的子类。和我们自己创建aidl一样, 至此,服务端的代码分析完了, 我们接下来看一下客户端。

客户端的调用, 和正常的bindService一样,采取显示intent的方式,(android 5.0以上必须采取显示intent的方式开启服务, 否则会抛异常)

private Messenger mMessenger;    ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            Log.e("LF", " iBinder : " + iBinder);            //根据iBinder创建一个Messenger对象            mMessenger = new Messenger(iBinder);            isConnection = true;            try {                iBinder.linkToDeath(new MyDeathRecipient(), 0);            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName componentName) {        }    };//开启服务的代码    @Override    public void onClick(View view) {        switch (view.getId()) {            //开启服务端的代码            case R.id.bindMessager:                Intent messagerIntent = new Intent(this, MessagerService.class);                this.bindService(messagerIntent, conn, BIND_AUTO_CREATE);                break;            case R.id.unBindMessager:                //unbind service的代码                if (isConnection) {                    this.unbindService(conn);                    isConnection = false;                }                break;            case R.id.invokeIPC:                //调用服务端的代码                if (isConnection && mMessenger != null) {                    Message message = Message.obtain();                    message.what = 10;                    message.arg1 = 21;                    try {                        mMessenger.send(message);                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }                break;            default:        }    }

当服务开启之后,我们在onServiceConnected()方法中可以获取到service端返回的iBinder对象。此iBinder对象在非IPC中,它就是MessengerImpl对象,如果在IPC中,那么此iBinder是BinderProxy, 它是一个代理。

        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            Log.e("LF", " iBinder : " + iBinder);            mMessenger = new Messenger(iBinder);            isConnection = true;            try {                iBinder.linkToDeath(new MyDeathRecipient(), 0);            } catch (RemoteException e) {                e.printStackTrace();            }        }

我们来看一下new Messenger(iBinder) 这句话,底层做了啥?

    public Messenger(IBinder target) {        mTarget = IMessenger.Stub.asInterface(target);    }

从上述代码里面可以很清楚的看到,其实它就是我们之前使用aidl的写法,将IMessenger.Stub.asInterface返回的对象,赋值给mTarget对象
来看一下IMessenger.Stub 中asInterface()方法的定义

public static android.os.IMessenger asInterface(android.os.IBinder obj) {    if ((obj==null)) {        return null;    }    //首先在本地找,如果找到,就直接返回    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);    if (((iin!=null)&&(iin instanceof android.os.IMessenger))) {        return ((android.os.IMessenger)iin);    }    //本地没有,就返回Stub.Proxy内部类对象    return new android.os.IMessenger.Stub.Proxy(obj);}

这里我们先不分析asInterface底层实现,只需要记住,如果是IPC,客户端获取到的是proxy.所以,这里mTarget是IMessenger.Stub的内部proxy
我们再来看一下mMessenger.send(message);这句底层实现

    public void send(Message message) throws RemoteException {        mTarget.send(message);    }

其实就是调用mTarget的send。也就是调用proxy的send

@Override public void send(android.os.Message msg) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();try {    _data.writeInterfaceToken(DESCRIPTOR);if ((msg!=null)) {    _data.writeInt(1);    msg.writeToParcel(_data, 0);} else {    _data.writeInt(0);}mRemote.transact(Stub.TRANSACTION_send, _data, null, android.os.IBinder.FLAG_ONEWAY);} finally {    _data.recycle();}}static final int TRANSACTION_send = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

我们看到是调用mRemote的transact方法,mRemote对象是我们传入的iBinder对象,其实最终会调用Stub的onTransact方法, 然后在onTransact方法里面进行switch根据传入的TRANSACTION_send 判断,最后调用的是MessengerImpl的send方法

        public void send(Message msg) {            msg.sendingUid = Binder.getCallingUid();            Handler.this.sendMessage(msg);        }

最终就会走正常的handler 的流程。

从以上的分析,可以看出,Messenger底层也是使用AIDL来实现的。在服务端通过Handler来构建一个MessengerImpl 的Bindler对象,将此Bindler对象通过onBind()方法返回, 在客户端,以bindService开启服务之后, 根据服务端传回来的iBinder对象创建一个Messenger对象, 这样客户端中的Messenger对象,就获取到了service端的IMessenger的代理(IPC, 非IPC是MessengerImpl对象)。这样,客户端和服务端,就可以通过Messenger的send方法进行通信了。

当然使用Messenger也可以从client端向service端的子线程发送handler消息, 只需要在service端构建Messenger的时候,传入一个带子线程Looper对象的Handler即可。

public class MessagerService extends Service {    public MessagerService() {    }    private Handler ipcHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            Log.e("LF", "msg.what : " + msg.what + ", msg.arg1 : " + msg.arg1);            Log.e("LF", "handleMessage thread : " + Thread.currentThread() + ", process : " + Process.myPid());        }    };    private  class MyAsyncHandler extends  Handler {        MyAsyncHandler(Looper looper) {            super(looper);        }        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            Log.e("LF", "msg.what : " + msg.what + ", msg.arg1 : " + msg.arg1);            Log.e("LF", "handleMessage thread : " + Thread.currentThread() + ", process : " + Process.myPid());        }    }    private Looper mHandlerLooper;    private  MyAsyncHandler myAsyncHandler;    private  Messenger mAsyncMessenger;    @Override    public void onCreate() {        super.onCreate();        //构建一个HandlerThread ,HandlerThread内部开启一个子线程,并且创建一个Looper,并进行loop循环。        HandlerThread handlerThread = new HandlerThread("MessengerHandlerThread");        handlerThread.start();        this.mHandlerLooper = handlerThread.getLooper();        this.myAsyncHandler = new MyAsyncHandler(mHandlerLooper);        //根据此Handler去构建一个Messenger对象        mAsyncMessenger = new Messenger(myAsyncHandler);    }    private Messenger messenger = new Messenger(ipcHandler);    @Override    public IBinder onBind(Intent intent) {        return  mAsyncMessenger.getBinder();    }    @Override    public void onDestroy() {        super.onDestroy();        this.mHandlerLooper.quit();//自己开启的loop一定要记得退出    }}

唯一注意一点的是,自己创建的Looper一定要记得调用quit或者quitSafe退出,否则,线程会一直存在。

如果服务端需要给客户端回应,那么在client端也构建一个Messenger对象,将Messenger对象赋值给message的replyTo,发送给service端,

Messenger 的内部是使用handler来处理消息的,所以,它是一个串行的过程。如果要处理并发的请求,或者跨进程调用service端的方法,请使用AIDL

0 0
原创粉丝点击