开发者社区> 一叶飘舟> 正文

Messenger:使用消息的跨进程通信

简介:
+关注继续查看

Messenger:信使

官方文档解释:它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。

以前我们使用Handler+Message的方式进行通信,都是在同一个进程中,从线程持有一个主线程的Handler对象,并向主线程发送消息。

而Android既然可以使用bindler机制进行跨进行通信,所以我们当然可以将Handler与bindler结合起来进行跨进程发送消息。

查看API就可以发现,Messenger就是这种方式的实现。

一般使用方法如下:

1。远程通过

Java代码 复制代码 收藏代码
  1. mMessenger = new Messenger(mHandler)
mMessenger = new Messenger(mHandler)

创建一个信使对象

2。客户端使用bindlerService请求连接远程

3。远程onBind方法返回一个bindler

Java代码 复制代码 收藏代码
  1. return mMessenger.getBinder();
return mMessenger.getBinder();

4.客户端使用远程返回的bindler得到一个信使(即得到远程信使)

Java代码 复制代码 收藏代码
  1. public void onServiceConnected(ComponentName name, IBinder service) {
  2. rMessenger = new Messenger(service);
  3.      ......
  4. }
			public void onServiceConnected(ComponentName name, IBinder service) {
				rMessenger = new Messenger(service);
        ......
			}

这里虽然是new了一个Messenger,但我们查看它的实现

Java代码 复制代码 收藏代码
  1. /**
  2. * Create a Messenger from a raw IBinder, which had previously been
  3. * retrieved with {@link #getBinder}.
  4. *
  5. * @param target The IBinder this Messenger should communicate with.
  6. */
  7. public Messenger(IBinder target) {
  8. mTarget = IMessenger.Stub.asInterface(target);
  9. }
    /**
     * Create a Messenger from a raw IBinder, which had previously been
     * retrieved with {@link #getBinder}.
     * 
     * @param target The IBinder this Messenger should communicate with.
     */
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }

发现它的mTarget是通过Aidl得到的,实际上就是远程创建的那个。

5。客户端可以使用这个远程信使对象向远程发送消息:rMessenger.send(msg);

这样远程服务端的Handler对象就能收到消息了,然后可以在其handlerMessage(Message msg)方法中进行处理。(该Handler对象就是第一步服务端创建Messenger时使用的参数mHandler).

经过这5个步骤貌似只有客户端向服务端发送消息,这样的消息传递是单向的,那么如何实现双向传递呢?

首先需要在第5步稍加修改,在send(msg)前通过msm.replyTo = mMessenger将自己的信使设置到消息中,这样服务端接收到消息时同时也得到了客户端的信使对象了,然后服务端可以通过

Java代码 复制代码 收藏代码
  1. //得到客户端的信使对象,并向它发送消息
  2. cMessenger = msg.replyTo;
  3. cMessenger.send(message);
//得到客户端的信使对象,并向它发送消息
cMessenger = msg.replyTo;
cMessenger.send(message);

即完成了从服务端向客户端发送消息的功能,这样客服端可以在自己的Handler对象的handlerMessage方法中接收服务端发送来的message进行处理。

双向通信宣告完成。

下面改写ApiDemos工程实现Messenger通信

MessengerService.java

Java代码 复制代码 收藏代码
  1. package com.xwangly.apidemo.app;
  2. import java.util.Random;
  3. import android.app.Service;
  4. import android.content.Intent;
  5. import android.os.Handler;
  6. import android.os.IBinder;
  7. import android.os.Message;
  8. import android.os.Messenger;
  9. import android.os.RemoteException;
  10. import android.util.Log;
  11. public class MessengerService extends Service {
  12. private String TAG = "MessengerService";
  13. @Override
  14. public void onDestroy() {
  15. // TODO Auto-generated method stub
  16. Log.i(TAG, "onDestroy");
  17. cMessenger = null;
  18. super.onDestroy();
  19. }
  20. @Override
  21. public boolean onUnbind(Intent intent) {
  22. // TODO Auto-generated method stub
  23. Log.i(TAG, "onUnbind");
  24. return super.onUnbind(intent);
  25. }
  26. static final int MSG_REGISTER_CLIENT = 1;
  27. static final int MSG_UNREGISTER_CLIENT = 2;
  28. static final int MSG_SET_VALUE = 3;
  29. private Random random = new Random();
  30. private Handler mHandler = new Handler() {
  31. @Override
  32. public void handleMessage(Message msg) {
  33. // TODO Auto-generated method stub
  34. Log.i(TAG, "handleMessage");
  35. switch (msg.what) {
  36. case MSG_SET_VALUE:
  37. try {
  38. Message message = Message.obtain(null,
  39. MessengerService.MSG_SET_VALUE);
  40. message.arg1 = random.nextInt(100);
  41. //得到客户端的信使对象,并向它发送消息
  42. cMessenger = msg.replyTo;
  43. cMessenger.send(message);
  44. } catch (RemoteException e) {
  45. // TODO Auto-generated catch block
  46. e.printStackTrace();
  47. }
  48. break;
  49. default:
  50. super.handleMessage(msg);
  51. }
  52. }
  53. };
  54. /**
  55. * 自己的信使对象
  56. */
  57. private Messenger mMessenger = new Messenger(mHandler);
  58. /**
  59. * 客户的信使
  60. */
  61. private Messenger cMessenger;
  62. @Override
  63. public IBinder onBind(Intent intent) {
  64. // TODO Auto-generated method stub
  65. Log.i(TAG, "onBind");
  66. //返回自己信使的bindler,以供客户端通过这个bindler得到服务端的信使对象(通过new Messenger(bindler))
  67. return mMessenger.getBinder();
  68. }
  69. @Override
  70. public void onRebind(Intent intent) {
  71. // TODO Auto-generated method stub
  72. Log.i(TAG, "onRebind");
  73. }
  74. }
package com.xwangly.apidemo.app;

import java.util.Random;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class MessengerService extends Service {
	private String TAG = "MessengerService";

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		Log.i(TAG, "onDestroy");
		cMessenger = null;
		super.onDestroy();
	}

	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onUnbind");
		return super.onUnbind(intent);
	}

	static final int MSG_REGISTER_CLIENT = 1;
	static final int MSG_UNREGISTER_CLIENT = 2;
	static final int MSG_SET_VALUE = 3;

	private Random random = new Random();

	private Handler mHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			Log.i(TAG, "handleMessage");
			switch (msg.what) {
			case MSG_SET_VALUE:
				try {
					Message message = Message.obtain(null,
							MessengerService.MSG_SET_VALUE);
					message.arg1 = random.nextInt(100);
					
					//得到客户端的信使对象,并向它发送消息
					cMessenger = msg.replyTo;
					cMessenger.send(message);
				} catch (RemoteException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				break;
			default:
				super.handleMessage(msg);
			}

		}
	};

	/**
	 * 自己的信使对象
	 */
	private Messenger mMessenger = new Messenger(mHandler);

	/**
	 * 客户的信使
	 */
	private Messenger cMessenger;

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onBind");
		//返回自己信使的bindler,以供客户端通过这个bindler得到服务端的信使对象(通过new Messenger(bindler))
		return mMessenger.getBinder();
	}

	@Override
	public void onRebind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onRebind");

	}

}

MessengerServiceActivities.java

Java代码 复制代码 收藏代码
  1. package com.xwangly.apidemo.app;
  2. import com.xwangly.apidemo.R;
  3. import android.app.Activity;
  4. import android.content.ComponentName;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.os.Bundle;
  8. import android.os.Handler;
  9. import android.os.IBinder;
  10. import android.os.Message;
  11. import android.os.Messenger;
  12. import android.os.RemoteException;
  13. import android.util.Log;
  14. import android.view.View;
  15. import android.widget.TextView;
  16. public class MessengerServiceActivities {
  17. public static class Binding extends Activity implements
  18. View.OnClickListener {
  19. private String TAG = "Binding";
  20. TextView mCallbackText;
  21. private boolean isBound;
  22. @Override
  23. protected void onCreate(Bundle savedInstanceState) {
  24. // TODO Auto-generated method stub
  25. super.onCreate(savedInstanceState);
  26. setContentView(R.layout.messenger_service_binding);
  27. findViewById(R.id.bind).setOnClickListener(this);
  28. findViewById(R.id.unbind).setOnClickListener(this);
  29. mCallbackText = (TextView) findViewById(R.id.callback);
  30. mCallbackText.setText("Not attached.");
  31. }
  32. private Handler mHandler = new Handler() {
  33. @Override
  34. public void handleMessage(Message msg) {
  35. Log.i(TAG, "handleMessage");
  36. switch (msg.what) {
  37. case MessengerService.MSG_SET_VALUE:
  38. mCallbackText.setText("Received from service: " + msg.arg1);
  39. break;
  40. default:
  41. super.handleMessage(msg);
  42. }
  43. }
  44. };
  45. /**
  46. * 自己的信使
  47. */
  48. private Messenger mMessenger;
  49. /**
  50. * 远程服务的信使
  51. */
  52. private Messenger rMessenger;
  53. private ServiceConnection connection = new ServiceConnection() {
  54. public void onServiceConnected(ComponentName name, IBinder service) {
  55. // TODO Auto-generated method stub
  56. Log.i(TAG, "onServiceConnected");
  57. rMessenger = new Messenger(service);
  58. mMessenger = new Messenger(mHandler);
  59. sendMessage();
  60. }
  61. public void onServiceDisconnected(ComponentName name) {
  62. // TODO Auto-generated method stub
  63. rMessenger = null;
  64. }
  65. };
  66. public void onClick(View v) {
  67. // TODO Auto-generated method stub
  68. Intent intent = new Intent(
  69. "com.xwangly.apidemo.app.messenger_service");
  70. switch (v.getId()) {
  71. case R.id.bind:
  72. if (!isBound) {
  73. isBound = bindService(intent, connection, BIND_AUTO_CREATE);
  74. //isBound = true;
  75. }else {
  76. sendMessage();
  77. }
  78. break;
  79. case R.id.unbind:
  80. if (isBound) {
  81. unbindService(connection);
  82. isBound = false;
  83. }
  84. break;
  85. default:
  86. break;
  87. }
  88. }
  89. /**
  90. * 使用服务端的信使向它发送一个消息。
  91. */
  92. private void sendMessage() {
  93. // TODO Auto-generated method stub
  94. Message message = Message.obtain(null, MessengerService.MSG_SET_VALUE);
  95. message.replyTo = mMessenger;
  96. try {
  97. rMessenger.send(message);
  98. } catch (RemoteException e) {
  99. // TODO Auto-generated catch block
  100. e.printStackTrace();
  101. }
  102. }
  103. }
  104. }
package com.xwangly.apidemo.app;

import com.xwangly.apidemo.R;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MessengerServiceActivities {
	public static class Binding extends Activity implements
			View.OnClickListener {
		private String TAG = "Binding";

		TextView mCallbackText;

		private boolean isBound;

		@Override
		protected void onCreate(Bundle savedInstanceState) {
			// TODO Auto-generated method stub
			super.onCreate(savedInstanceState);
			setContentView(R.layout.messenger_service_binding);
			findViewById(R.id.bind).setOnClickListener(this);
			findViewById(R.id.unbind).setOnClickListener(this);

			mCallbackText = (TextView) findViewById(R.id.callback);
			mCallbackText.setText("Not attached.");

		}

		private Handler mHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				Log.i(TAG, "handleMessage");
				switch (msg.what) {
				case MessengerService.MSG_SET_VALUE:
					mCallbackText.setText("Received from service: " + msg.arg1);
					break;
				default:
					super.handleMessage(msg);
				}
			}
		};

		/**
		 * 自己的信使
		 */
		private Messenger mMessenger;
		
		/**
		 * 远程服务的信使
		 */
		private Messenger rMessenger;
		
		private ServiceConnection connection = new ServiceConnection() {

			public void onServiceConnected(ComponentName name, IBinder service) {
				// TODO Auto-generated method stub
				Log.i(TAG, "onServiceConnected");
				rMessenger = new Messenger(service);
				mMessenger = new Messenger(mHandler);
				
				sendMessage();
			}


			public void onServiceDisconnected(ComponentName name) {
				// TODO Auto-generated method stub
				rMessenger = null;
			}
		};

		public void onClick(View v) {
			// TODO Auto-generated method stub
			Intent intent = new Intent(
					"com.xwangly.apidemo.app.messenger_service");
			switch (v.getId()) {
			case R.id.bind:
				if (!isBound) {
					isBound = bindService(intent, connection, BIND_AUTO_CREATE);
					//isBound = true;
				}else {
					sendMessage();
				}
				break;
			case R.id.unbind:
				if (isBound) {
					unbindService(connection);
					isBound = false;
				}
				break;
			default:
				break;
			}
		}
		
		/**
		 * 使用服务端的信使向它发送一个消息。
		 */
		private void sendMessage() {
			// TODO Auto-generated method stub
			Message message = Message.obtain(null, MessengerService.MSG_SET_VALUE);
			message.replyTo = mMessenger;
			try {
				rMessenger.send(message);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}

AndroidManifest.xml相关配置如下:

Xml代码 复制代码 收藏代码
  1. <service android:name=".app.MessengerService" >
  2. <intent-filter>
  3. <action android:name="com.xwangly.apidemo.app.messenger_service" />
  4. </intent-filter>
  5. </service>
  6. <activity android:name=".app.MessengerServiceActivities$Binding"
  7. android:label="@string/activity_messenger_service_binding"
  8. android:launchMode="singleTop">
  9. <intent-filter>
  10. <action android:name="android.intent.action.MAIN" />
  11. <category android:name="android.intent.category.LAUNCHER" />
  12. </intent-filter>
  13. </activity>
		<service android:name=".app.MessengerService" >
			<intent-filter>
				<action android:name="com.xwangly.apidemo.app.messenger_service" />
			</intent-filter>
		</service>
        <activity android:name=".app.MessengerServiceActivities$Binding"
                android:label="@string/activity_messenger_service_binding"
                android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

至于layout就不帖了,两个按钮一个文本域。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Kafka消息delivery可靠性保证(Message Delivery Semantics)
原文见:http://kafka.apache.org/documentation.html#semantics kafka在生产者和消费者之间的传输是如何保证的,我们可以知道有这么几种可能提供的delivery guarantee: At most once 消息可能会丢,但绝不会重复传输 At least one 消息绝不会丢,但可能会重复传输 Exactly once 每条消息肯定会被传输一次且仅传输一次,很多时候这是用户所想要的。
1142 0
使用Docker生成SSL证书
本文讲的是使用Docker生成SSL证书【编者的话】学习如何使用Docker生成SSL证书,而不是在主机上生成。
2533 0
怎样使用阿里云消息服务?
阿里云消息服务(Message Service)是一种高效、可靠、安全、便捷、可弹性扩展的分布式消息服务。MNS能够帮助应用开发者在他们应用的分布式组件上自由的传递数据、通知消息,构建松耦合系统。 消息服务同时支持各种类型消息推送,其中和短信前后端的无缝整合更高效的为用户提供了大批量短信发送能力。
1796 0
【c#】队列(Queue)和MSMQ(消息队列)的基础使用
原文:【c#】队列(Queue)和MSMQ(消息队列)的基础使用       首先我们知道队列是先进先出的机制,所以在处理并发是个不错的选择。然后就写两个队列的简单应用。 Queue 命名空间     命名空间:System.Collections,不在这里做过多的理论解释,这个东西非常的好理解。
1209 0
【C++中消息自动派发之四】使用IDL构建Chat Server
  前一篇blog 讲了如何实现IDL 解析器,本篇通过IDL解析器构建一个聊天服务器程序。本程序用来测试IDL解析器的功能,网络层使用前边blog中介绍的ffown库。我们只需定义chat.idl文件,idl解析器自动生成消息排放代码,省了每次再去繁琐的编写消息解析、判断代码。
1166 0
RocketMq消息队列使用
最近在看消息队列框架 ,alibaba的RocketMQ单机支持1万以上的持久化队列,支持诸多特性, 目前RocketMQ在阿里集团被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景 比kafka还是有过之无不及,其实kafka文档很丰富 但RocketMQ网上的...
1615 0
+关注
1635
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载