Android进程间的通信之Messenger

Android进程间的通信方式可以通过以下两种方式完成:

1 Android接口定义语言(AIDL)
2 使用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使用步骤

1、服务端实现一个Handler,由其接收来自客户端的每个调用的回调
2、使用第1步的Handler的实例作为target创建Messenger对象(即该Messenger持有了对Handler的引用)
3、使用Messenger创建一个IBinder(通过调用Messenger的getBinder()方法),服务端的onBind()方法中将其返回到客户端
4、客户端使用IBinder将Messenger(引用服务端的Handler实例)实例化,然后使用后者将Message对象发送给服务端
5、服务端在其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

 1 public class MainActivity extends Activity {
 2     private static final int REPLY_MSG_ID = 2;
 3     private boolean mServiceConnected = false;
 4     private Button btn = null;
 5     //用于向Service端发送消息的Messenger
 6     private Messenger mBoundServiceMessenger = null;
 7     //用于接收Service发送消息的Messenger
 8     private final Messenger mReceiveMessenger = new Messenger(new ReceiveMessHandler(this));
 9     private ServiceConnection conn = new ServiceConnection() {
10         @Override
11         public void onServiceDisconnected(ComponentName name) {
12             mBoundServiceMessenger = null;
13             mServiceConnected = false;
14         }
15
16         @Override
17         public void onServiceConnected(ComponentName name, IBinder service) {
18             mBoundServiceMessenger = new Messenger(service);
19             mServiceConnected = true;
20         }
21     };
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.activity_main);
26         btn = (Button)findViewById(R.id.button);
27         bindService(new Intent(this, MessengerService.class), conn, Context.BIND_AUTO_CREATE);
28         btn.setOnClickListener(new View.OnClickListener() {
29             @Override
30             public void onClick(View v) {
31                 if(mServiceConnected){
32                     //获取消息对象
33                     Message msg = Message.obtain(null, 1, 0, 0);
34                     try{
35                         //replyTo参数包含客户端Messenger
36                         msg.replyTo = mReceiveMessenger;
37                         //向Service端发送消息
38                         mBoundServiceMessenger.send(msg);
39                     }catch(RemoteException re){
40                         re.printStackTrace();
41                     }
42                 }
43             }
44         });
45     }
46     @Override
47     protected void onDestroy() {
48         super.onDestroy();
49         if(mServiceConnected){
50             unbindService(conn);
51             mServiceConnected = false;
52         }
53     }
54     /**
55      * 客户端实现一个Handler用于接收服务端返回的响应
56      * @author Administrator
57      *
58      */
59     static class ReceiveMessHandler extends Handler{
60         //持有当前Activity的弱引用,避免内存泄露
61         private final WeakReference<MainActivity> mActivity;
62         public ReceiveMessHandler(MainActivity activity){
63             mActivity = new WeakReference<MainActivity>(activity);
64         }
65         @Override
66         public void handleMessage(Message msg) {
67             switch(msg.what){
68             case REPLY_MSG_ID:
69                 Toast.makeText(mActivity.get(), msg.getData().getString("msg"), Toast.LENGTH_SHORT).show();
70                 break;
71             }
72         }
73     }
74 }

服务端:MessengerService.java

 1 public class MessengerService extends Service {
 2     private static final int REPLY_MSG_ID = 2;
 3     private static final int MSG_ID = 1;
 4     static class BoundServiceHandler extends Handler{
 5         private final WeakReference<MessengerService> mService;
 6         public BoundServiceHandler(MessengerService service){
 7             mService = new WeakReference<MessengerService>(service);
 8         }
 9         @Override
10         public void handleMessage(Message msg) {
11             switch(msg.what){
12             case MSG_ID:
13                 Messenger replyMessenger = msg.replyTo;
14                 Message replyMsg = Message.obtain(null, REPLY_MSG_ID);
15                 //向客户端响应的消息内容
16                 Bundle b = new Bundle();
17                 b.putString("msg", "this is the message reply from service");
18                 replyMsg.setData(b);
19                 try{
20                     replyMessenger.send(replyMsg);
21                 }catch(RemoteException re){
22                     re.printStackTrace();
23                 }
24                 break;
25                 default:
26                     super.handleMessage(msg);
27             }
28         }
29     }
30     private final Messenger mMessenger = new Messenger(new BoundServiceHandler(this));
31     @Override
32     public IBinder onBind(Intent intent) {
33         Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
34         return mMessenger.getBinder();
35     }
36 }

此外,上述例子中所有的Handler的实现类都被声明为static并使用Service或Activity的WeakReference。如果不这样做,编译器会给出警告信息“This handler class should be static or leaks might occur”。通过使用弱引用的方式,就允许Service或Activity进行垃圾收集了。

时间: 2024-10-25 19:26:31

Android进程间的通信之Messenger的相关文章

Android进程间的通信之AIDL

Android服务被设计用来执行很多操作,比如说,可以执行运行时间长的耗时操作,比较耗时的网络操作,甚至是在一个单独进程中的永不会结束的操作.实现这些操作之一是通过Android接口定义语言(AIDL)来完成的.AIDL被设计用来执行进程间通信,另一种实现方式见博文Android进程间的通信之Messenger.本文我们将学习如何创建AIDL文件实现Android进程间通信.在正式学习之前,我们先澄清一些"事实". 关于Android Service 1.Android服务不是后台任务

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

本文首先概述了Android的进程间通信的Binder机制,然后结合一个AIDL的例子,对Binder机制进行了解析. 概述 我们知道,在Android app中的众多activity,service等组件可以运行在同一进程中,也可以运行在不同进程中.当组件运行在同一进程中进行通信就显得比较简单,在之前的Android线程间通信机制中已经讲过了:而当它们运行在不同的进程中时,就需要使用我们本文中所要介绍的Binder机制了. Binder作为一种进程间通信机制,负责提供远程调用的功能(RPC),

Android进程间的通信

1.概述:由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些.在android SDK中提供了4种用于跨进程通讯的方式.这4种方式正好对应于android系统中4种应用程序组件:Activity.Content Provider.Broadcast和Service.其中Activity可以跨进程调用其他应用程序的Activity:Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可

Android进阶笔记04:Android进程间通讯之Messenger ( 区别于AIDL)

一. Android进程间通讯之Messenger 的引入 (1)引言:      平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽.哈哈.此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信:甚至作为一个转接处,任意两个进程都能通过服务端进行通信. (2) Messenger 与 AIDL 比较:    

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

在Android中,如果我们需要在不同进程间实现通信,就需要用到AIDL技术去完成. AIDL(android Interface Definition Language)是一种接口定义语言,编译器通过*.aidl文件的描述信息生成符合通信协议的Java代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作.关于AIDL的编写规则我在这里就不多介绍了,读者可以到网上查找一下相关资料. 接下来,我就演示一个操作AIDL的最基本的流程. 首先,我

【转】使用AIDL实现进程间的通信之复杂类型传递

使用AIDL实现进程间的通信之复杂类型传递 首先要了解一下AIDL对Java类型的支持. 1.AIDL支持Java原始数据类型. 2.AIDL支持String和CharSequence. 3.AIDL支持传递其他AIDL接口,但你引用的每个AIDL接口都需要一个import语句,即使位于同一个包中. 4.AIDL支持传递实现了android.os.Parcelable接口的复杂类型,同样在引用这些类型时也需要import语句.(Parcelable接口告诉Android运行时在封送(marsha

使用AIDL实现进程间的通信

在Android中,如果我们需要在不同进程间实现通信,就需要用到AIDL技术去完成. AIDL(Android Interface Definition Language)是一种接口定义语言,编译器通过*.aidl文件的描述信息生成符合通信协议的Java代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作.关于AIDL的编写规则我在这里就不多介绍了,读者可以到网上查找一下相关资料. 接下来,我就演示一个操作AIDL的最基本的流程. 首先,我

进程间的通信如何实现

进程间的通信如何实现 版权声明:本文为博主原创文章,未经博主允许不得转载.

linux 进程间的通信

现在linux使用的进程间通信方式:(1)管道(pipe)和有名管道(FIFO)(2)信号(signal)(3)消息队列(4)共享内存(5)信号量(6)套接字(socket) 为何进行进程间的通信:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到.C.通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程).D.资源共享