frameworkAndroid知识Android开发经验谈

Messenger是如何封装AIDL接口的?

2017-07-17  本文已影响143人  未见哥哥

Messenger 可以用于进程间通讯,其底层就是使用 AIDL 实现。Messenger 封装了一个IMessenger 类型的属性 mTarget ,它是 Messenger 实现进程间通讯的核心类。

1、创建 Messenegr

上面的描述可能有点模糊,没关系先来了解一下如何创建 Messenegr :

这里涉及到一个 Handler ,它得作用是什么呢?因为客户端需要给服务端发送消息,而学过 AIDL 的同学都知道,客户端其实操作的是服务端远程接口的代理对象,真正实现功能就是 MessengerImpl 这个对象,代理对象实际通过 Binder 调用 MessengerImpl 中真正的方法去发送 message,而 Handler 就是用于调度 message 信息。

private final IMessenger mTarget;

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

final IMessenger getIMessenger() {
    synchronized (mQueue) {
        if (mMessenger != null) {
            return mMessenger;
        }
        mMessenger = new MessengerImpl();
        return mMessenger;
    }
}
public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

我们在上面讲了,客户端给服务端发送消息实际上操作的是远程服务接口的代理对象 mTarget ,它内部会调用远程接口的真正实现类 MessengerImpl 完成消息的发送。

2、服务端与客户端通讯示例代码

2.1、服务端实现

public Messenger(Handler target) {
    //真正实现类
    mTarget = target.getIMessenger();
}

final IMessenger getIMessenger() {
    synchronized (mQueue) {
        if (mMessenger != null) {
            return mMessenger;
        }
        //实际返回的是 MessengerImpl 对象
        mMessenger = new MessengerImpl();
        return mMessenger;
    }
}
public IBinder getBinder() {
    //将第一步创建的 mTarget 实体对象转化为 Binder
    return mTarget.asBinder();
}
private static class MessengerHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
            case 1:
                //接受客户端传递过来的消息
                Bundle bundle = msg.getData();
                System.out.println(bundle.getString("msg"));
                //回应客户端
                //拿到这个 msg 对应的 Messenger
                Messenger client = msg.replyTo;
                //构造一个你要发送的消息
                Message message=Message.obtain();
                message.what=2;
                Bundle data = new Bundle();
                data.putString("msg","服务端收到了客户端的消息拉");
                message.setData(data);
                //通过 Messenger 发送消息给客户端
                try {
                    client.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }
    }
}
/**
 * 服务端收到客户端的消息之后,回应客户端
 *
 */
public class MessengerService extends Service {
    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    //接受客户端传递过来的消息
                    Bundle bundle = msg.getData();
                    System.out.println(bundle.getString("msg"));

                    //回应客户端
                    //拿到这个 msg 对应的 Messenger
                    Messenger client = msg.replyTo;

                    //构造一个你要发送的消息
                    Message message=Message.obtain();
                    message.what=2;

                    Bundle data = new Bundle();
                    data.putString("msg","服务端收到了客户端的消息拉");

                    message.setData(data);
                    //通过 Messenger 发送消息给客户端
                    try {
                        client.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

    private final Messenger messenger = new Messenger(new MessengerHandler());

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}

2.2、客户端实现



//根据服务端传来的 IBinder 对象创建一个 Messenger
mServiceMessenger = new Messenger(service);
   

//通过 IBinder 创建 Messenger
public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}
private final Messenger mGetReplyMessenger = new Messenger(new GetMessageHandler());
private static class GetMessageHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
            case 2:
                Bundle data = msg.getData();
                String result = data.getString("msg");
                System.out.println("receive from server:"+result);
                break;
        }
    }
}
//当服务建立连接之后就发送数据给服务端
Message msg = Message.obtain();
msg.what = 1;
//跨进程通讯不能使用 message.obj 这个属性,应该使用 bundle 否则会出现Can't marshal non-Parcelable ob
//msg.obj = "say hello to server";
Bundle bundle = new Bundle();
bundle.putString("msg", "say hello to server");
msg.setData(bundle);
//将 Messenger 传递给服务端
msg.replyTo = mGetReplyMessenger;
public class MainActivity extends AppCompatActivity {
    private Messenger mServiceMessenger;

    private static class GetMessageHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case 2:
                    Bundle data = msg.getData();
                    String result = data.getString("msg");
                    System.out.println("receive from server:"+result);

                    break;
            }
        }
    }

    private final Messenger mGetReplyMessenger = new Messenger(new GetMessageHandler());

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, MessengerService.class);

        //绑定服务
        bindService(intent, conn, Service.BIND_AUTO_CREATE);
    }

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //根据服务端传来的 IBinder 对象创建一个 Messenger
            mServiceMessenger = new Messenger(service);

            //当服务建立连接之后就发送数据给服务端
            Message msg = Message.obtain();
            msg.what = 1;
            //跨进程通讯不能使用 message.obj 这个属性,应该使用 bundle 否则会出现Can't marshal non-Parcelable objects across processes.
            //msg.obj = "say hello to server";
            Bundle bundle = new Bundle();
            bundle.putString("msg", "say hello to server");
            msg.setData(bundle);
            //将 Messenger 传递给服务端
            msg.replyTo = mGetReplyMessenger;
            //给远程服务发送消息
            try {
                mServiceMessenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (conn != null) {
            unbindService(conn);
        }
    }
}

3、使用 Message.replyTo 属性将 Messenger 传递给服务端

这里涉及到给客户端回应消息的情况,其过程大概是这样的,首先客户端给服务端发送消息 message ,并且在该 message.replyTo 属性添加在客户端创建的 Messenger 对象(实际上这时的 Messenger 就是 IMessener 的真正实现者),它内部维护了一个 handler 对象,当服务端获取到这个客户端通过 message 传递过来的 Messenger 对象(实际上就是 IMessenger 的代理对象)之后,构造一个 message 对象(服务端回应给客户端的消息)并通过 messenger 发送给客户端。这里要注意:Messenger 是实现了 Parcelable 接口,因此它可以在进程间进行传输。

public final class Messenger implements Parcelable

我们都知道进程间通讯就是对传输的数据进行序列化和反序列化的过程,而 Messenger 是可以进行进程间传输的,我们在最开始的时候提过, Messenger 实际上是对 IMessenger 的封装,所以将 Messenger 传递给服务端,我们应该更加关注其封装的 IMessnger 是怎么被被转化为 IBinder 对象传递过去。因此我们想要了解 Messenger 是怎么被传输的,那么直接看 replyTo 携带的 Messenger 的内部是怎么实现 Parcelable 的序列化和反序列化就好了

public void writeToParcel(Parcel dest, int flags) {
    if (callback != null) {
        throw new RuntimeException(
            "Can't marshal callbacks across processes.");
    }
    dest.writeInt(what);
    dest.writeInt(arg1);
    dest.writeInt(arg2);
    if (obj != null) {
        try {
            Parcelable p = (Parcelable)obj;
            dest.writeInt(1);
            dest.writeParcelable(p, flags);
        } catch (ClassCastException e) {
            throw new RuntimeException(
                "Can't marshal non-Parcelable objects across processes.");
        }
    } else {
        dest.writeInt(0);
    }
    dest.writeLong(when);
    dest.writeBundle(data);
    //将replyTo这个 Messenger 进行序列化
    Messenger.writeMessengerOrNullToParcel(replyTo, dest);
    dest.writeInt(sendingUid);
}

下面代码就是将 Messenger 内部的 mTarget 转化为 IBinder 进行远程传输。

public static void writeMessengerOrNullToParcel(Messenger messenger,
        Parcel out) {
    out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
            : null);
}

Messenger 序列化过程就是将 IMessenger 实体转化为 IBinder ,而反序列化就是将获取到的 IBinder 转化未 IMessenger 对象的过程(在 Messenger 构造实现)。

public static Messenger readMessengerOrNullFromParcel(Parcel in) {
    IBinder b = in.readStrongBinder();
    return b != null ? new Messenger(b) : null;
}

4、知识点

上一篇下一篇

猜你喜欢

热点阅读