大家好,欢迎来到IT知识分享网。
(一) 前言
Messager n.信使,信差; 先驱; [军]通信兵,传令兵; 顾名思义,Messenger就像一个信使一样,可以负责双方的数据传递。当然如果只是单向传递的话一个Messager就可以了,如果需要双向传递的话那么肯定两个进程里面各有一个信使(一个人怎么通信呢?对不对)。其实Messager实现IPC通信,底层也是使用了AIDL方式。
思想:在进程A中创建一个Message,将这个Message对象通过IMessenger.send(message)方法传递到进程B(当然,Message对象本身是无法被传递到进程B的,send(message)方法会使用一个Parcel对象对Message对象编集,再将Parcel对象传递到进程B中,然后解编集,得到一个和进程A中Message对象内容一样的对象),再把Message对象加入到进程B的消息队列里,Handler会去处理它。
(二) 相关知识的准备
那么讲到Messenger的话,就不能不提下跟它相关的几个知识点。
1. Service Android里面使用非常的Service, 没有操作界面,在后台提供服务
2. Handler Android里面线程通信类,非常有意思的设计
(三) 如何使用Messenger
1.搭建Service端
public class MessengerService extends Service { / * Target we publish for clients to send messages to IncomingHandler. */ final Messenger mServiceMessenger = new Messenger(new IncomingHandler()); / * Command to the service to register a client, receiving callbacks * from the service. The Message's replyTo field must be a Messenger of * the client where callbacks should be sent. */ public static final int MSG_REGISTER_CLIENT = 1; / * Command to the service to unregister a client, ot stop receiving callbacks * from the service. The Message's replyTo field must be a Messenger of * the client as previously given with MSG_REGISTER_CLIENT. */ public static final int MSG_UNREGISTER_CLIENT = 2; / * Command to service to set a new value. This can be sent to the * service to supply a new value, and will be sent by the service to * any registered clients with the new value. */ public static final int MSG_SET_VALUE = 3; / Keeps track of all current registered clients. */ ArrayList<Messenger> mClients = new ArrayList<Messenger>(); / Holds last value set by a client. */ int mValue = 0; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); // Display a notification about us starting. } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return mServiceMessenger.getBinder(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub return super.onUnbind(intent); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub switch (msg.what) { case MSG_REGISTER_CLIENT: mClients.add(msg.replyTo); break; case MSG_UNREGISTER_CLIENT: mClients.remove(msg.replyTo); break; case MSG_SET_VALUE: mValue = msg.arg1; for (int i = mClients.size() - 1; i >= 0; i--) { try { mClients.get(i).send(Message.obtain(null, MSG_SET_VALUE, mValue, 0)); } catch (RemoteException e) { // The client is dead. Remove it from the list; // we are going through the list from back to front // so this is safe to do inside the loop. mClients.remove(i); } } break; default: super.handleMessage(msg); break; } } } }
2
.搭建Client
public class MessengerActivity extends Activity { Messenger mClientMessenger = new Messenger(new IncomingHandler()); Messenger mServiceMessenger = null; SubServiceConn mSubServiceConn; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.messager); mSubServiceConn = new SubServiceConn(); bindService(new Intent(this, MessengerService.class), mSubServiceConn, Context.BIND_AUTO_CREATE); } / * Handler of incoming messages from service. */ class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MessengerService.MSG_SET_VALUE: mCallbackText.setText("Received from service: " + msg.arg1); break; default: super.handleMessage(msg); } } } private class SubServiceConn implements ServiceConnection {// 定义Service连接, @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub mIsBound = true; mServiceMessenger = new Messenger(service);// 拿到进程A里面MessengerA的引用,并保存起来 mCallbackText.setText("Attached."); Message m = Message.obtain(null, MessengerService.MSG_REGISTER_CLIENT); // 新建一个Message m.replyTo = mClientMessenger; try { mServiceMessenger.send(m); // Give it some value as an example. m = Message.obtain(null,MessengerService.MSG_SET_VALUE, this.hashCode(), 0); mServiceMessenger.send(m); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 向进程A,通过MessengerA通信 } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub mIsBound = false; mServiceMessenger=null; mCallbackText.setText("Disconnected."); } } }
理解
:
1.首先要bindService(Intent service, ServiceConnection conn, int flags),将接口ServiceConnection传递给服务端。
2.服务端创建一个Messager信使final Messenger mServiceMessenger = new Messenger(new IncomingHandler()); 并通过onBind返回给客户端,为什么要用服务端的Messager呢?我的理解是属于两个进程,相当于两个程序,你想给自己通信跟定要用自己的东西啊!
3.客户端实现接口ServiceConnection的方法public void onServiceConnected(ComponentName name, IBinder service);并通过mServiceMessenger = new Messenger(service);拿到进程Service里面mServiceMessenger的引用,并保存起来,然后再mServiceMessenger.send(message);通过Service的messager(信使)向Service通信了,到这里单向通信应经完成了,你只需要在Service的handler里面去接受message就像了。要说一下这里的mServiceMessenger = new Messenger(service);并不是new 出一个新的对象,Create a Messenger from a raw IBinder, which had previously been retrieved with {@link #getBinder}.
public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }
如果英语和我一样不好的话可以只看几个单词 a raw(原始),previously(之前的),IMessenger.Stub.asInterface(target)方法会在进程Client中创建一个IMessenger的代理类Proxy(aidl),当使用mServiceMessenger发送一条消息时,实际调用的是代理类Proxy的send(Message msg)方法。看一下源码:
第2步中的new Messager
public Messenger(Handler target) { mTarget = target.getIMessenger(); }
Handler类的方法:
final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } } private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { Handler.this.sendMessage(msg); } }
至此
,Messager初始化完成,接下来看一下public IBinder onBind(Intent intent)
private final IMessenger mTarget; public IBinder getBinder() { return mTarget.asBinder(); }
IMessenger的代码如果没有的话可以看这里: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/os/IMessenger.java#IMessenger.Stub.Proxy.send%28android.os.Message%29
如过被墙了的话:
/* 2 * This file is auto-generated. DO NOT MODIFY. 3 * Original file: frameworks/base/core/java/android/os/IMessenger.aidl 4 */ 5 package android.os; Hide: 6 7 public interface More ...IMessenger extends android.os.IInterface 8 { Local-side IPC implementation stub class. 9 10public static abstract class More ...Stub extends android.os.Binder implements android.os.IMessenger 11{ 12private static final java.lang.String DESCRIPTOR = "android.os.IMessenger"; Construct the stub at attach it to the interface. 13 14public More ...Stub() 15{ 16this.attachInterface(this, DESCRIPTOR); 17} Cast an IBinder object into an android.os.IMessenger interface, generating a proxy if needed. 21 22public static android.os.IMessenger More ...asInterface(android.os.IBinder obj) 23{ 24if ((obj==null)) { 25return null; 26} 27android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR); 28if (((iin!=null)&&(iin instanceof android.os.IMessenger))) { 29return ((android.os.IMessenger)iin); 30} 31return new android.os.IMessenger.Stub.Proxy(obj); 32} 33public android.os.IBinder More ...asBinder() 34{ 35return this; 36} 37@Override public boolean More ...onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException 38{ 39switch (code) 40{ 41case INTERFACE_TRANSACTION: 42{ 43reply.writeString(DESCRIPTOR); 44return true; 45} 46case TRANSACTION_send: 47{ 48data.enforceInterface(DESCRIPTOR); 49android.os.Message _arg0; 50if ((0!=data.readInt())) { 51_arg0 = android.os.Message.CREATOR.createFromParcel(data); 52} 53else { 54_arg0 = null; 55} 56this.send(_arg0); 57return true; 58} 59} 60return super.onTransact(code, data, reply, flags); 61} 62private static class More ...Proxy implements android.os.IMessenger 63{ 64private android.os.IBinder mRemote; 65More ...Proxy(android.os.IBinder remote) 66{ 67mRemote = remote; 68} 69public android.os.IBinder More ...asBinder() 70{ 71return mRemote; 72} 73public java.lang.String More ...getInterfaceDescriptor() 74{ 75return DESCRIPTOR; 76} 77public void More ...send(android.os.Message msg) throws android.os.RemoteException 78{ 79android.os.Parcel _data = android.os.Parcel.obtain(); 80try { 81_data.writeInterfaceToken(DESCRIPTOR); 82if ((msg!=null)) { 83_data.writeInt(1); 84msg.writeToParcel(_data, 0); 85} 86else { 87_data.writeInt(0); 88} 89mRemote.transact(Stub.TRANSACTION_send, _data, null, android.os.IBinder.FLAG_ONEWAY); 90} 91finally { 92_data.recycle(); 93} 94} 95} 96static final int TRANSACTION_send = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); 97} 98public void More ...send(android.os.Message msg) throws android.os.RemoteException; 99}
通过上面的代码可以明显的看到当在onServiceConnected中new Messenger(IBinder target)的时候会调用到IMessenger.Stub.asInterface(target);而Stub.asInterface的操作是return new android.os.IMessenger.Stub.Proxy(obj
);当使用mMessengerService发送一条消息时,实际调用的是代理类Proxy的send(Message msg)方法。而send()的方法是什么呢?上面也有android.os.Parcel _data = android.os.Parcel.obtain();msg.writeToParcel(_data, 0);将Message msg的内容写到Parcel _data对象中。然后调用进程Service返回的IBinder对象的transact方法
Default implementation rewinds the parcels and calls onTransact. On the remote side, transact calls into the binder to do the IPC. 290 291 public final boolean More ...transact(int code, Parcel data, Parcel reply, 292 int flags) throws RemoteException { 293 if (false) Log.v("Binder", "Transact: " + code + " to " + this); 294 if (data != null) { 295 data.setDataPosition(0); 296 } 297 boolean r = onTransact(code, data, reply, flags); 298 if (reply != null) { 299 reply.setDataPosition(0); 300 } 301 return r; 302 }
网址:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/os/Binder.java#Binder.onTransact%28int%2Candroid.os.Parcel%2Candroid.os.Parcel%2Cint%29">http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/os/Binder.java#Binder.onTransact%28int%2Candroid.os.Parcel%2Candroid.os.Parcel%2Cint%29
{
switch (code)
{
……..
case TRANSACTION_send:
{
data.enforceInterface(DESCRIPTOR);
android.os.Message _arg0;
if ((0!=data.readInt())) {
_arg0 = android.os.Message.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.send(_arg0);
return true;
}
…….
这个方法在进程B中恢复进程A传递过来的消息,然后调用this.send(_arg0);。再来看看send(_arg0)这个方法
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
Handler.this.sendMessage(msg);
}
}
4.如果想双向通信
1.在Client端 创建自己的Messenger mClientMessenger = new Messenger(new IncomingHandler());
2.实现IncomingHandler的handleMessage接受Service返回的信息
3.message.replyTo = mClientMessenger;通过message将mClientMessenger传递到服务端
4.Service在handleMessage中通过msg.replyTo获得mClientMessenger
5.不要忘记配置清单文件
参考:http://blog.csdn.net/chenfeng0104/article/details/
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/152457.html