Android进程间的通信之Messenger
Android进程间的通信方式可以通过以下两种方式完成:
Android接口定义语言(AIDL)
使用Messenger绑定服务
本文我们将学习使用Messenger绑定服务的方式进行进程间的通信。
Android AIDL和Messenger区别
使用Messenger是执行进程间通信最简单的方法,因为Messenger会在单一线程中创建包含所有请求的队列,这样您就不必对服务进行线程安全设计。而纯粹的AIDL接口会同时向服务发送多个请求,服务随后必须应对多线程处理。AIDL通常应用在服务被设计到单独的应用中的场景(即服务端可客户端不属于同一个app的情况),而Messenger通常应用在同一app的不同进程的场景中。
Messenger基本思想
服务端(被动方)提供一个Service来处理客户端(主动方)连接,维护一个Handler(具体来讲:是Handler的子类)来创建Messenger,在onBind时返回Messenger的binder(调用Messenger的getBinder()方法,该方法返回一个IBinder对象,客户端将通过该对象作为参数创建一个Messenger对象用于与服务端进行通信)。
Messenger使用步骤
、服务端实现一个Handler,由其接收来自客户端的每个调用的回调
、使用第1步的Handler的实例作为target创建Messenger对象(即该Messenger持有了对Handler的引用)
、使用Messenger创建一个IBinder(通过调用Messenger的getBinder()方法),服务端的onBind()方法中将其返回到客户端
、客户端使用IBinder将Messenger(引用服务端的Handler实例)实例化,然后使用后者将Message对象发送给服务端
、服务端在其Handler中接收每个Message
这样,客户端并没有调用服务端的“方法”,而客户端传递的消息(Message对象)是服务端在其Handler中接收到的。
如果想让服务端对客户端发回响应,则还需要在客户端中创建一个持有客户端Handler实现类的Messenger,当客户端收到onServiceConnected()回调时,在向服务发送的Message时,send()方法的replyTo参数中需包含客户端的Messenger。这样,客户端就可在其Handler实现类中接收到来自服务端的响应消息。
简单示例
AndroidMainfest.xml
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="yf.exam.client.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MessengerService" android:process=":custom_process"/>
</application>
在上面的配置文件中,service的android:process属性用于在一个单独进程中启动service,看如下图片:

布局文件很简单,这里只有一个按钮,用于向服务端发送消息并显示服务端响应内容,这里不再给出。
客户端:MainActivity
public class MainActivity extends Activity {
private static final int REPLY_MSG_ID = ;
private boolean mServiceConnected = false;
private Button btn = null;
//用于向Service端发送消息的Messenger
private Messenger mBoundServiceMessenger = null;
//用于接收Service发送消息的Messenger
private final Messenger mReceiveMessenger = new Messenger(new ReceiveMessHandler(this));
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mBoundServiceMessenger = null;
mServiceConnected = false;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBoundServiceMessenger = new Messenger(service);
mServiceConnected = true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.button);
bindService(new Intent(this, MessengerService.class), conn, Context.BIND_AUTO_CREATE);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mServiceConnected){
//获取消息对象
Message msg = Message.obtain(null, , , );
try{
//replyTo参数包含客户端Messenger
msg.replyTo = mReceiveMessenger;
//向Service端发送消息
mBoundServiceMessenger.send(msg);
}catch(RemoteException re){
re.printStackTrace();
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mServiceConnected){
unbindService(conn);
mServiceConnected = false;
}
}
/**
* 客户端实现一个Handler用于接收服务端返回的响应
* @author Administrator
*
*/
static class ReceiveMessHandler extends Handler{
//持有当前Activity的弱引用,避免内存泄露
private final WeakReference<MainActivity> mActivity;
public ReceiveMessHandler(MainActivity activity){
mActivity = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case REPLY_MSG_ID:
Toast.makeText(mActivity.get(), msg.getData().getString("msg"), Toast.LENGTH_SHORT).show();
break;
}
}
}
}
服务端:MessengerService.java
public class MessengerService extends Service {
private static final int REPLY_MSG_ID = ;
private static final int MSG_ID = ;
static class BoundServiceHandler extends Handler{
private final WeakReference<MessengerService> mService;
public BoundServiceHandler(MessengerService service){
mService = new WeakReference<MessengerService>(service);
}
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case MSG_ID:
Messenger replyMessenger = msg.replyTo;
Message replyMsg = Message.obtain(null, REPLY_MSG_ID);
//向客户端响应的消息内容
Bundle b = new Bundle();
b.putString("msg", "this is the message reply from service");
replyMsg.setData(b);
try{
replyMessenger.send(replyMsg);
}catch(RemoteException re){
re.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
private final Messenger mMessenger = new Messenger(new BoundServiceHandler(this));
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
此外,上述例子中所有的Handler的实现类都被声明为static并使用Service或Activity的WeakReference。如果不这样做,编译器会给出警告信息“This handler class should be static or leaks might occur”。通过使用弱引用的方式,就允许Service或Activity进行垃圾收集了。
Android进程间的通信之Messenger的更多相关文章
- Android进程间的通信之AIDL
Android服务被设计用来执行很多操作,比如说,可以执行运行时间长的耗时操作,比较耗时的网络操作,甚至是在一个单独进程中的永不会结束的操作.实现这些操作之一是通过Android接口定义语言(AIDL ...
- 从AIDL开始谈Android进程间Binder通信机制
转自: http://tech.cnnetsec.com/585.html 本文首先概述了Android的进程间通信的Binder机制,然后结合一个AIDL的例子,对Binder机制进行了解析. 概述 ...
- Android进程间的通信
1.概述:由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些.在android SDK中提供了4种用于跨进程通讯的方式.这4种方式正好对应于 ...
- Android 进程间的通信
localsocket: https://blog.csdn.net/azhengye/article/details/73863404 https://www.cnblogs.com/basta ...
- Android进阶笔记04:Android进程间通讯(IPC)之Messenger
一. Android进程间通讯之Messenger 的引入 (1)引言: 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...
- android 进程间通信 messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯? android 消息机制 进程间 android 进程间 可以用 handler么 messenger 与 handler 机制 messenger 机制 是不是 就是 handler 机制 或 , 是不是就是 消息机制 android messenge
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯 ...
- Android 使用AIDL实现进程间的通信
在Android中,如果我们需要在不同进程间实现通信,就需要用到AIDL技术去完成. AIDL(android Interface Definition Language)是一种接口定义语言,编译器通 ...
- Android进程间通讯
最近研究了一下Android进程间通讯,原来只是会用,但是只是会用是不行滴,就来研究一下. 刚开始看的时候,我的头是这么大,看了一夜的时候,头就变成这样了,,吓得宝宝赶紧上床休息了,. 先喝喝茶讲个故 ...
- Android 进程间通讯方式
Android 进程间通讯方式 1.通过单向数据管道传递数据 管道(使用PipedWriter/ 创建PipedReader)是java.io包的一部分.也就是说,它们是一般的Java功能,而不是An ...
随机推荐
- Spark Streaming资源动态申请和动态控制消费速率剖析
本期内容 : Spark Streaming资源动态分配 Spark Streaming动态控制消费速率 为什么需要动态处理 : Spark 属于粗粒度资源分配,也就是在默认情况下是先分配好资源然后再 ...
- Thread.sleep(0)的意义& 多线程
我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢?思考下面这两个问题: 假设现在是 2008-4-7 12:00:00.000,如果我调用 ...
- NodeJS学习三之API
Node采用V8引擎处理JavaScript脚本,最大特点就是单线程运行,一次只能运行一个任务.这导致Node大量采用异步操作(asynchronous opertion),即任务不是马上执行,而是插 ...
- NSSortDescriptor对象进行数组排序
//创建一个数组 NSArray *array = @[@"zhangsan", @"lisi", @"zhonger", @"z ...
- C#的自定义滚动条
VS工具箱自带的滚动条,不能设置颜色. 在网上找资源,找到一个控制TextBox的垂直滚动条,链接为http://www.cnblogs.com/2seek/p/4455079.html 在这个的基础 ...
- MVC过滤器详解
MVC过滤器详解 APS.NET MVC中(以下简称"MVC")的每一个请求,都会分配给相应的控制器和对应的行为方法去处理,而在这些处理的前前后后如果想再加一些额外的逻辑处理. ...
- Java泛型-内部原理: 类型擦除以及类型擦除带来的问题
一:Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除.Java的泛型基本上都是在编译 ...
- WinForm程序中的类TextBox的自定义控件, 添加失去焦点的功能
原理: 一.在控件的后台代码中, 添加布尔类型的属性CanFocus 二.在控件的构造函数中, 注册Enter事件的处理方法. 并在处理方法中,根据CanFocus属性的值来决定是否可以丢失焦点, 如 ...
- 企业级监控平台开发之nagios二次开发(七)
背景: A公司里有很多服务器(>3000台),每台服务器都有不同的用途,如DB Server.WEB Server.ESXI等,每个组使用其中的一批,每个组可能有多个服务器管理员.现在问题出来了 ...
- Maven项目导入后打红色X
在所有的配置都正确的情况,程序能正常运行跑起来,看一下problem下的红色错误 如果这两个错误不影响你的程序,或者已经配置或处理,直接右击删除这两个错就行了. 删除之后,就没有了吧,OK搞定