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的更多相关文章

  1. Android进程间的通信之AIDL

    Android服务被设计用来执行很多操作,比如说,可以执行运行时间长的耗时操作,比较耗时的网络操作,甚至是在一个单独进程中的永不会结束的操作.实现这些操作之一是通过Android接口定义语言(AIDL ...

  2. 从AIDL开始谈Android进程间Binder通信机制

    转自: http://tech.cnnetsec.com/585.html 本文首先概述了Android的进程间通信的Binder机制,然后结合一个AIDL的例子,对Binder机制进行了解析. 概述 ...

  3. Android进程间的通信

    1.概述:由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些.在android SDK中提供了4种用于跨进程通讯的方式.这4种方式正好对应于 ...

  4. Android 进程间的通信

    localsocket:   https://blog.csdn.net/azhengye/article/details/73863404 https://www.cnblogs.com/basta ...

  5. Android进阶笔记04:Android进程间通讯(IPC)之Messenger

    一. Android进程间通讯之Messenger 的引入 (1)引言:      平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...

  6. 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 进程间 通讯 ...

  7. Android 使用AIDL实现进程间的通信

    在Android中,如果我们需要在不同进程间实现通信,就需要用到AIDL技术去完成. AIDL(android Interface Definition Language)是一种接口定义语言,编译器通 ...

  8. Android进程间通讯

    最近研究了一下Android进程间通讯,原来只是会用,但是只是会用是不行滴,就来研究一下. 刚开始看的时候,我的头是这么大,看了一夜的时候,头就变成这样了,,吓得宝宝赶紧上床休息了,. 先喝喝茶讲个故 ...

  9. Android 进程间通讯方式

    Android 进程间通讯方式 1.通过单向数据管道传递数据 管道(使用PipedWriter/ 创建PipedReader)是java.io包的一部分.也就是说,它们是一般的Java功能,而不是An ...

随机推荐

  1. WEBPACK开始

    这是一个非常简单的例子,通过这个例子你将学习到 1.How to install webpack 2.How to use webpack 3.How to use loaders 4.How to ...

  2. bugfree安装 centos

    bugfree团队早已不做支持,转作禅道管理了,关于其中恩怨可以参见http://www.bugfree.cn/ 组里同事要用此做管理,所以写此文档,以备后用 ==================== ...

  3. CString转string

    如题,找了半天... //CString转string USES_CONVERSION; CString temp; temp = _T("kjdsaflkjdlfkj"); ch ...

  4. 常用的dos命令

    cd 进入一个目录 cd .. 返回上一个目录 dir 遍历目录 上下键 查找输入过的命令 Tab键 命令自动补齐

  5. R语言获取国内的股票数据

    quantmod 包默认是访问 yahoo finance 的数据,其中包括上证和深证的股票数据,还有港股数据. 上证代码是 ss,深证代码是 sz,港股代码是 hk 例如苏宁云商 setSymbol ...

  6. Apache ab压力测试时出现大量的错误原因分析

    最近有一个测试任务,是测试nginx的并发请求到底能够达到多少的, 于是就用ab工具对其进行压力测试. 这压力测试一执行,问题就来了:发起10000次请求,并发100,错误的情况能达到30%--50% ...

  7. sort详解2

    linux sort 命令详解 sort是在Linux里非常常用的一个命令,管排序的,集中精力,五分钟搞定sort,现在开始! 1 sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比 ...

  8. ng-style 的坑 - 对性能的影响

    本文地址:http://www.cnblogs.com/jying/p/5633203.html 熟悉 angular 的前端对ng-style 一定不陌生,这个家伙可以绑定一个函数,使得我们可以在函 ...

  9. ArcEngine批量添加XY数据

    使用ArcGIS Desktop “添加XY数据”或者“创建XY事件图层”工具 可以导入Excel坐标数据,生成临时图层并添加至ArcMap.ArcGlobe或者ArcScene中.在ArcEngin ...

  10. macbook 重装win7

    若是第一次已经成功好了,并且把第一次的安装U盘WININSTALL内容保存完好的前提下, win7要重新安装. 先进入Boot Camp移除Windows,备份好你的WIN系统的重要文件. 把第一次的 ...