Android 多进程之Messenger的使用
Android多进程系列
- Android 多进程通信之几个基本问题
- Android多进程之Binder的使用
- Android多进程之手动编写Binder类
- Android多进程之Binder解绑监听的问题
- Android多进程之Binder的意外死亡及权限校验
Messenger也可以作为Android多进程的一种通信方式,通过构建Message来在客户端和服务端之间传递数据
简单使用Messenger
客户端通过Messenger向服务端进程发送消息
- 构建一个运行在独立进程中的服务端Service:
public class MessengerService extends Service {
private static final String TAG = "MessagerService";
/**
* 处理来自客户端的消息,并用于构建Messenger
*/
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case MESSAGE_FROM_CLIENT:
Log.e(TAG, "receive message from client:" + message.getData().getString("msg"));
break;
default:
super.handleMessage(message);
break;
}
}
}
/**
* 构建Messenger对象
*/
private final Messenger mMessenger = new Messenger(new MessengerHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
//将Messenger对象的Binder返回给客户端
return mMessenger.getBinder();
}
}
- 注册service,当然要设置在不同的进程
<service
android:name="com.xxq2dream.service.MessengerService"
android:process=":remote" />
- 然后客户端是通过绑定服务端返回的binder来创建Messenger对象,并通过这个Messenger对象来向服务端发送消息
public class MessengerActivity extends AppCompatActivity {
private static final String TAG = "MessengerActivity";
private Messenger mService;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.e(TAG, "ServiceConnection-->" + System.currentTimeMillis());
//通过服务端返回的Binder创建Messenger
mService = new Messenger(iBinder);
//创建消息,通过Bundle传递数据
Message message = Message.obtain(null, MESSAGE_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("msg", "hello service,this is client");
message.setData(bundle);
try {
//向服务端发送消息
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e(TAG, "onServiceDisconnected-->binder died");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messenger);
//绑定服务
Intent intent = new Intent(this, MessengerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
//解绑服务
unbindService(mConnection);
super.onDestroy();
}
}
通过上面的额实践,我们可以看出利用Messenger进行跨进程通信,需要通过Message来传递消息,而Message可以通过setData方法利用Bundle来传递复杂的数据。
服务端如果要回复消息给客户端,那就要用到Message的replyTo参数了
- 服务端改造
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case Constant.MESSAGE_FROM_CLIENT:
Log.e(TAG, "receive message from client:" + message.getData().getString("msg"));
//获取客户端传递过来的Messenger,通过这个Messenger回传消息给客户端
Messenger client = message.replyTo;
//当然,回传消息还是要通过message
Message msg = Message.obtain(null, Constant.MESSAGE_FROM_SERVICE);
Bundle bundle = new Bundle();
bundle.putString("msg", "hello client, I have received your message!");
msg.setData(bundle);
try {
client.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(message);
break;
}
}
}
- 客户端改造,主要是通过Handle构建一个Messenger对象,并在向服务端发送消息的时候,通过Message的replyTo参数将Messenger对象传递给服务端
/**
* 用于构建客户端的Messenger对象,并处理服务端的消息
*/
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case Constant.MESSAGE_FROM_SERVICE:
Log.e(TAG, "receive message from service:" + message.getData().getString("msg"));
break;
default:
super.handleMessage(message);
break;
}
}
}
/**
* 客户端Messenger对象
*/
private Messenger mClientMessenger = new Messenger(new MessengerHandler());
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.e(TAG, "ServiceConnection-->" + System.currentTimeMillis());
mService = new Messenger(iBinder);
Message message = Message.obtain(null, MESSAGE_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("msg", "hello service,this is client");
message.setData(bundle);
//将客户端的Messenger对象传递给服务端
message.replyTo = mClientMessenger;
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e(TAG, "onServiceDisconnected-->binder died");
}
};
总结
- 使用Messager来传递Message,Message中能使用的字段只有what、arg1、arg2、Bundle和replyTo,自定义的Parcelable对象无法通过object字段来传输
- Message中的Bundle支持多种数据类型,replyTo字段用于传输Messager对象,以便进程间相互通信
- Messager以串行的方式处理客户端发来的消息,不适合有大量并发的请求
- Messager方法只能传递消息,不能跨进程调用方法
欢迎关注我的微信公众号,期待与你一起学习,一起交流,一起成长!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
Android Button、TabLayout的英文字是大写的?
参考 我的Android进阶之旅------>android Button上面的英文字符串自动大写的问题解决android在使用过程中,解决 Button 和 TabLayout 英文自动大写的问题 如图 1、未解决前的,button内英文文字是大写的,而textview正常 0.png 2、解决后,button内英文文字正常 1.png 解决 1、第一个联想到的就是button控件的大小写属性,可是在button里我没设置啊?奇怪。。。那就找找看哪里出了问题 1.1、layout中的button,用的style=btn_normal_style <Button android:id="@+id/btn_show_dialog" style="@style/btn_normal_style" android:text="弹出Dialog" /> 1.2、btn_normal_style 没有关于大小写的。。继续btn_base_style <!-- button style --> <style name="btn_normal_style" par...
-
下一篇
29.FFmpeg+OpenGLES+OpenSLES播放器实现(三.FFmpeg配置和编译脚本)
项目源码FFmpeg开发文档 编译过程中涉及到很多ndk中的so库和头文件以及交叉编译的工具,在命令执行的时候会在ndk相应的目录下去查找,所以我们可以使用export命令事先将这些路径设置到环境变量,使用的时候可以很方便的找到 //NDK加入环境变量,以我的ndk存放路径为例 export NDK=/root/renzhenming/ffmpeg/android-ndk-r14b //ndk的platforms文件夹中存放的是各个版本架构下的so库和头文件 export PLATFORM=$NDK/platforms/android-21/arch-arm //指定交叉编译工具的路径 export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 //指定输出类型,以armv7-a为例 export CPU=armv7-a //指定so文件编译后的输出路径 export PREFIX=./android/$CPU 相关命令解析 脚本中定义了一个方法build_ffmpeg,最终它被调用两...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS关闭SELinux安全模块
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL数据库在高并发下的优化方案
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7,8上快速安装Gitea,搭建Git服务器