Android-Android进程间通讯之messenger

转自‘https://www.cnblogs.com/makaruila/p/4869912.html

平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯。它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽。哈哈。

此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信;甚至作为一个转接处,任意两个进程都能通过服务端进行通信。

与 AIDL 比较:

  当您需要执行 IPC 时,为您的接口使用 Messenger 要比使用 AIDL 实现更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。

  对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。

接下来看下怎么用:

服务端:

1.创建一个handler对象,并实现hanlemessage方法,用于接收来自客户端的消息,并作处理

2.创建一个messenger(送信人),封装handler

3.用messenger的getBinder()方法获取一个IBinder对象,通过onBind返回给客户端

客户端:

1.在activity中绑定服务

2.创建ServiceConnection并在其中使用 IBinder 将 Messenger实例化

3.使用Messenger向服务端发送消息

4.解绑服务

5.服务端中在 handleMessage() 方法中接收每个 Message

这样,客户端并没有调用服务的“方法”。而客户端传递的“消息”(Message 对象)是服务在其 Handler 中接收的。

上面实现的仅仅是单向通信,即客户端给服务端发送消息,如果我需要服务端给客户端发送消息又该怎样做呢?

其实,这也是很容易实现的,下面就让我们接着上面的步骤来实现双向通信吧

1.在客户端中创建一个Handler对象,用于处理服务端发过来的消息

2.创建一个客户端自己的messenger对象,并封装handler。

3.将客户端的Messenger对象赋给待发送的Message对象的replyTo字段

4.在服务端的Handler处理Message时将客户端的Messenger解析出来,并使用客户端的Messenger对象给客户端发送消息

这样就实现了客户端和服务端的双向通信了。

注意:注:Service在声明时必须对外开放,即android:exported="true"

是不是看的头晕,忘掉吧,直接看下面。

看一个简单的例子

 1 package com.zixue.god.myapplication;
 2
 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.widget.Toast;
11
12 //服务端service
13 public class MyService extends Service {
14     private static final int CODE = 1;
15     public MyService() {
16     }
17     @Override
18     public IBinder onBind(Intent intent) {
19         return mMessenger.getBinder();
20     }
21
22     //创建一个送信人,封装handler
23     private Messenger mMessenger = new Messenger(new Handler() {
24         @Override
25         public void handleMessage(Message msg) {
26             Message toClient = Message.obtain();
27             switch (msg.what) {
28                 case CODE:
29                     //接收来自客户端的消息,并作处理
30                     int arg = msg.arg1;
31                     Toast.makeText(getApplicationContext(),arg+"" , Toast.LENGTH_SHORT).show();
32                     toClient.arg1 = 1111111111;
33                     try {
34                         //回复客户端消息
35                         msg.replyTo.send(toClient);
36                     } catch (RemoteException e) {
37                         e.printStackTrace();
38                     }
39             }
40             super.handleMessage(msg);
41         }
42     });
43 }

//客户端

 1 package com.zixue.god.fuck;
 2
 3 import android.content.ComponentName;
 4 import android.content.Intent;
 5 import android.content.ServiceConnection;
 6 import android.os.Bundle;
 7 import android.os.Handler;
 8 import android.os.IBinder;
 9 import android.os.Message;
10 import android.os.Messenger;
11 import android.os.RemoteException;
12 import android.support.v7.app.AppCompatActivity;
13 import android.util.Log;
14 import android.view.View;
15 import android.widget.Button;
16 import android.widget.Toast;
17
18 public class MainActivity extends AppCompatActivity {
19     private boolean mBond;
20     private Messenger serverMessenger;
21     private MyConn conn;
22
23     @Override
24     protected void onCreate(Bundle savedInstanceState) {
25         super.onCreate(savedInstanceState);
26         setContentView(R.layout.activity_main);
27         //绑定服务
28         Intent intent = new Intent();
29         intent.setAction("com.zixue.god.myapplication.server");
30         conn = new MyConn();
31         bindService(intent, conn, BIND_AUTO_CREATE);
32         Button button = (Button) findViewById(R.id.bt);
33         button.setOnClickListener(new View.OnClickListener() {
34             @Override
35             public void onClick(View v) {
36                 Message clientMessage = Message.obtain();
37                 clientMessage.what = 1;
38                 clientMessage.arg1 = 12345;
39                 try {
40                     clientMessage.replyTo = mMessenger;
41                     serverMessenger.send(clientMessage);
42                 } catch (RemoteException e) {
43                     e.printStackTrace();
44                 }
45             }
46         });
47     }
48
49     private class MyConn implements ServiceConnection {
50
51         @Override
52         public void onServiceConnected(ComponentName name, IBinder service) {
53             //连接成功
54             serverMessenger = new Messenger(service);
55             Log.i("Main", "服务连接成功");
56             mBond = true;
57         }
58
59         @Override
60         public void onServiceDisconnected(ComponentName name) {
61             serverMessenger = null;
62             mBond = false;
63         }
64     }
65     private Messenger mMessenger = new Messenger(new Handler(){
66         @Override
67         public void handleMessage(Message msg) {
68             Toast.makeText(getApplicationContext(),msg.arg1+"",Toast.LENGTH_SHORT).show();
69             super.handleMessage(msg);
70         }
71     });
72     @Override
73     protected void onDestroy() {
74         if (mBond) {
75             unbindService(conn);
76         }
77         super.onDestroy();
78     }
79
80 }

这样就实现了客户端和服务端双向通信,是不是很简单呢。

  其实messenger底层也是AIDL。客户端和服务端通讯,就是普通的AIDL,客户端实例化stub之后,通过stub的send方法把消息发到服务端。服务端和客户端通讯:服务端通过解析message的replyto,获得客户端的stub,然后通过send方法发送到客户端。有精力的可以去翻一下源码。

原文地址:https://www.cnblogs.com/hustcser/p/10228995.html

时间: 2024-10-29 13:04:52

Android-Android进程间通讯之messenger的相关文章

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

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

Android进程间通讯之messenger

这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下. 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽.哈哈. 此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信:甚至作为一个转接处,任意两个进程都能通过服务端进行通信. 与 AIDL 比较: 当您

一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】

本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder机制,在网上查阅了大量的资料,也看了老罗的Binder系列的博客和Innost的深入理解Binder系列的博客,都是从底层开始讲的,全是C代码,虽然之前学过C和C++,然而各种函数之间花式跳转,看的我都怀疑人生.毫不夸张的讲每看一遍都是新的内容,跟没看过一样.后来又看到了Gityuan的博客看到了一

Android AIDL 进行进程间通讯(IPC)

编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3.AIDL默认支持的类型包括java基本类型 (int.long.boolean等) 和 (String.List.Map.CharSequence),使用这些类型时不需要import声明.对于List和Map中的元素类型必须是AIDL支持的类型,如果使用自定义类型作为参数或者返回值,自定义类型必须实

android 不同进程间的调用 AIDL 实现通讯服务

android 不同进程间的调用  AIDL 实现通讯服务 最近对aidl android 不同进程间的调用,不同运用间的调用做了一些尝试: 步骤如下: 1:首先在要被调用的程序里写好服务service 具体代码如下: package com.jiaruihua.service.demo; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.I

Android(IPC)进程间通讯1:详解Binder由来?

完整原文:http://tryenough.com/android-ipc1 Android开发的进程间通讯,整个Android的应用都依赖于binder做底层通信机制.而Linux中提供的进程间通讯方式并没有binder机制,那么android中为什么要单独创造这种通讯方式呢?带着这个问题,继续往下读. Linux中进程相关概念 Linux将系统内存划分成了 用户空间 和 内核空间 两部分: 用户空间 : 普通应用程序则运行在用户空间上,它们不能使用某些特定的系统功能,不能直接访问硬件,不能直

服务 远程服务 AIDL 进程间通讯 IPC

Activity aidl接口文件 package com.bqt.aidlservice;  interface IBinderInterface {     /* 更改文件后缀为[.aidl]去掉public等所有修饰符.         更改后,会在gen目录下生成一个同名的.java文件,此java文件中有一个名为[Stub]的内部类,此内部类继承自Binder类且实现了我们这里定义的IBinderInterface接口         此内部类的[asInterface(IBinder

进程间通讯与同步的实现

进程通讯 内存共享 A进程创建共享区 shmget(-) 映射内存共享区 shmat(-) B进程通过key找到共享区 映射内存共享区 进程间通讯 撤销各自的内存映射 shmdt() 删除共享区 shctl() 管道Pipe A进程与B进程进行相互通讯 需要建立两个管道 当A->B时,需要在A中write end 在B中read end:当写入满时,管道阻塞:当管道无东西看读时 同样阻塞: ***以下代码为Xcode上的实现 因为VS下不支持某些类库 *** // // main.c // Pi

win32进程间通讯--共享内存

小白一枚,如有不对,请各位大神多多指教! 最近看了看win32进程间通讯.简单写了写利用共享内存实现进程间通讯 使用共享内存实现进程间通讯: 1.在WM_CREATE消息下创建文件映射内核对象 1 hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUF_SIZE, (LPCWSTR)szName); 2.在需要进行数据共享的地方映射缓存区视图,将要写入的数据放入pbuf 1 pBuf = (c