Android进程间通讯——Messager(信使)

(一) 前言

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

public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException

{
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/7010244
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值