Android 进程间通信之使用Messenger

早就知道使用Messenger可以进行进程间通讯,还是感觉很混乱,所以,看了些资料,自己总结一下。


Messenger翻译为信使,顾名思义,就是传递消息。那么,我们今天讨论的是在进程之间传递消息。使用Messenger进行进程间通讯总体来说还是比较简单的,是一种轻量级的IPC方案,它的底层是实现了AIDL,在这里,我们只需要了解即可,不讨论AIDL。

先来理顺一下这个传递消息的机制,涉及到几个概念,发信人、收信人、信使、信、动作(动作就是收信人在收到信息之后做出的动作)。结合到我们的进程间来,收信人就是服务端(以service的形式运行在另外一个进程),动作就是服务端收到信后做出的操作(handler),发信人就是客户端(以Activity的形式运行在一个进程),信使即Messenger,信就是Message。

根据我们目前的理解,大致理一下 服务端(MessengerService)和客户端(MessengeActivity)各自需要做什么,

服务端(MessengerService):

1)声明信使(Messenger)

2)定义动作(handler)

客户端(MessengerActivity):

1)连接服务端(这里是绑定服务:bindService)

2)声明信使(Messenger)

3)定义消息(Message)

4)用信使将消息发出

   

到这里,我们产生了个疑问,如何能确定服务端的信使就是客户端发出的信使呢?

 这时,我们需要一个“令牌”来表明该信使身份。在Android里,用来充当“令牌”的是Binder。


首先,服务端声明一个信使(Messenger),并定义出该信使(Messenger)收到信息后所进行的操作(Handler) ; 然后,客户端在连接服务端时,需要获得服务端已定义的信使(Messenger)的Binder,然后客户端在自己的进程里用拿到的IBinder声明一个Messenger,此时,客户端用此信使发送的消息变会准确到达服务端并进行相对于的操作(Handler)。 理解了以上这些原理,便很容易理解代码啦。


下面,我们先来介绍Messenger这个类,下面是它的两个构造函数

    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }
第一个构造方法的参数是Handle,此构造方法用于服务端的定义,用来绑定该信使(Messenger)的对应的动作(Handler);第二个构造方法的参数是Binder,此构造方法用于客户端的定义,通过连接服务端时获得的IBinder来进行定义,可以确保此Messenger即为服务端所对应的Messenger,服务端可以进行相应的操作(Handler)。


说到这里,可以上代码啦,此代码我们有两个例子,一个是服务端只接收了信息,只显示出来,不回复客户端;另一个例子是 服务端也做出来回复。

一、服务端只接收不回复的:

服务端:(注意:Service要在清单配置文件里注册)

public class MessengerService extends Service{

	public static final String TAG="MessengerService";
	
	private static class MessengerHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MyConstants.MSG_FROM_CLIENT:
				Log.i(TAG, "receive msg from Client :"+msg.getData().getString("msg"));
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}
	
	private final Messenger mMessenger=new Messenger(new MessengerHandler());
	
	@Override
	public IBinder onBind(Intent intent) {
		return mMessenger.getBinder();
	}

}
配置文件(android:process这个属性,可以将该服务放在指定的进程(这里放在其它进程))
        <service 
            android:name=".messenger.MessengerService"
            android:process=":remote"
            >
            <intent-filter>
                <action android:name="com.zzh.MessengerService.launch"/>
            </intent-filter>
        </service>


客户端:

public class MessengerActivity extends Activity{
	
	private static final String TAG="MessengerActivity";
	
	private Messenger mService;
	
	private ServiceConnection mConnection=new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mService=new Messenger(service);
			Log.i(TAG, "bind service");
			Message msg=Message.obtain(null, MyConstants.MSG_FROM_CLIENT);
			Bundle data=new Bundle();
			data.putString("msg", "hello,this is client.");
			msg.setData(data);
			try {
				mService.send(msg);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_messenger);
		Intent intent=new Intent("com.zzh.MessengerService.launch");
		bindService(intent, mConnection, BIND_AUTO_CREATE);
	}
	
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		unbindService(mConnection);
		super.onDestroy();
	}
	
}
运行结果:


我们在服务端的进程里,将客户端(与服务端不再一个进程)里传递的消息显示出来,说明进程间消息传递成功。



二、服务端回复(只需要再增加一次Messenger通信,服务端为本次通信的“客户端”,客户端为本次通信的“服务端”)

服务端:(改变不多,增加了一个Messenger client)

public class MessengerService extends Service{

	public static final String TAG="MessengerService";
	
	private static class MessengerHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MyConstants.MSG_FROM_CLIENT:
				Log.i(TAG, "receive msg from Client :"+msg.getData().getString("msg"));
				Messenger client=msg.replyTo;
				Message replyMessage=Message.obtain(null, MyConstants.MSG_FROM_SERVICE);
				Bundle bundle=new Bundle();
				bundle.putString("reply", "恩,你的消息我已经收到,稍后回复你");
				replyMessage.setData(bundle);
				try {
					client.send(replyMessage);
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}
	
	private final Messenger mMessenger=new Messenger(new MessengerHandler());
	
	@Override
	public IBinder onBind(Intent intent) {
		return mMessenger.getBinder();
	}

}
客户端:增加一个Messenger类型的对象 mGetReplyMessenger,和用于处理该信使的Handler(MessengerHandler)
public class MessengerActivity extends Activity{
	
	private static final String TAG="MessengerActivity";
	
	private Messenger mService;
	private final Messenger mGetReplyMessenger=new Messenger(new MessengerHandler());
	
	private static class MessengerHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MyConstants.MSG_FROM_SERVICE:
				Log.i(TAG, "receive msg from Service: "+msg.getData().getString("reply"));
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}
	
	private ServiceConnection mConnection=new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mService=new Messenger(service);
			Log.i(TAG, "bind service");
			Message msg=Message.obtain(null, MyConstants.MSG_FROM_CLIENT);
			Bundle data=new Bundle();
			data.putString("msg", "hello,this is client.");
			msg.setData(data);
			//一定要注意这句
			msg.replyTo=mGetReplyMessenger;
			try {
				mService.send(msg);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_messenger);
		Intent intent=new Intent("com.zzh.MessengerService.launch");
		bindService(intent, mConnection, BIND_AUTO_CREATE);
	}
	
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		unbindService(mConnection);
		super.onDestroy();
	}
	
}
结果显示:

服务端收到客户端的消息:



客户端收到服务端的返回消息:





PS: 我主要是结合《Android开发艺术探索》中来总结的,作为自己的学习笔记。

这是第一篇博客,希望自己能坚持写下去,加油,Android菜鸟的进阶路开始啦~~~





猜你喜欢

转载自blog.csdn.net/qq_32142513/article/details/52930902