Android跨进程通信Messenger
一.概述

我们可以在客户端发送一个Message给服务端,在服务端的handler中会接收到客户端的消息,然后进行对应的处理,处理完成后,再将结果等数据封装成Message,发送给客户端,客户端的handler中会接收到处理的结果。
有这么几个特点:
基于Message,相信大家都很熟悉
支持回调的方式,也就是服务端处理完成长任务可以和客户端交互
不需要编写aidl文件
此外,还支持,记录客户端对象的Messenger,然后可以实现一对多的通信;甚至作为一个转接处,任意两个进程都能通过服务端进行通信,这个后面再说。
二.应用
package com.imooc.messenger_server; import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException; public class MessengerService extends Service { private static final int MSG_SUM = 0x110; //最好换成HandlerThread的形式
private Messenger mMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msgfromClient) {
Message msgToClient = Message.obtain(msgfromClient);//返回给客户端的消息
switch (msgfromClient.what) {
//msg 客户端传来的消息
case MSG_SUM:
msgToClient.what = MSG_SUM;
try {
//模拟耗时
Thread.sleep();
msgToClient.arg2 = msgfromClient.arg1 + msgfromClient.arg2;
msgfromClient.replyTo.send(msgToClient);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
super.handleMessage(msgfromClient);
}
}); @Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}
服务端就一个Service,可以看到代码相当的简单,只需要去声明一个Messenger对象,然后onBind方法返回mMessenger.getBinder();
然后坐等客户端将消息发送到handleMessage想法,根据message.what去判断进行什么操作,然后做对应的操作,最终将结果通过 msgfromClient.replyTo.send(msgToClient);返回。
可以看到我们这里主要是取出客户端传来的两个数字,然后求和返回,这里我有意添加了sleep(2000)模拟耗时,注意在实际使用过程中,可以换成在独立开辟的线程中完成耗时操作,比如和HandlerThread结合使用。
注册文件
<service
android:name=".MessengerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.zhy.aidl.calc"></action>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
(二)客户端
Activity
package com.imooc.messenger_client; import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView; public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int MSG_SUM = 0x110; private Button mBtnAdd;
private LinearLayout mLyContainer;
//显示连接状态
private TextView mTvState; private Messenger mService;
private boolean isConn; private Messenger mMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msgFromServer) {
switch (msgFromServer.what) {
case MSG_SUM:
TextView tv = (TextView) mLyContainer.findViewById(msgFromServer.arg1);
tv.setText(tv.getText() + "=>" + msgFromServer.arg2);
break;
}
super.handleMessage(msgFromServer);
}
}); private ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
isConn = true;
mTvState.setText("connected!");
} @Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
isConn = false;
mTvState.setText("disconnected!");
}
}; private int mA; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //开始绑定服务
bindServiceInvoked(); mTvState = (TextView) findViewById(R.id.id_tv_callback);
mBtnAdd = (Button) findViewById(R.id.id_btn_add);
mLyContainer = (LinearLayout) findViewById(R.id.id_ll_container); mBtnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
int a = mA++;
int b = (int) (Math.random() * ); //创建一个tv,添加到LinearLayout中
TextView tv = new TextView(MainActivity.this);
tv.setText(a + " + " + b + " = caculating ...");
tv.setId(a);
mLyContainer.addView(tv); Message msgFromClient = Message.obtain(null, MSG_SUM, a, b);
msgFromClient.replyTo = mMessenger;
if (isConn) {
//往服务端发送消息
mService.send(msgFromClient);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}); } private void bindServiceInvoked() {
Intent intent = new Intent();
intent.setAction("com.zhy.aidl.calc");
bindService(intent, mConn, Context.BIND_AUTO_CREATE);
Log.e(TAG, "bindService invoked !");
} @Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConn);
}
}
代码也不复杂,首先bindService,然后在onServiceConnected中拿到回调的service(IBinder)对象,通过service对象去构造一个mService =new Messenger(service);然后就可以使用mService.send(msg)给服务端了。
Android跨进程通信Messenger的更多相关文章
- 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇
前言 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Andro ...
- android跨进程通信(IPC)——AIDL
转载请标明出处: http://blog.csdn.net/sinat_15877283/article/details/51026711: 本文出自: [温利东的博客] 近期在看 @任玉刚 大神编写 ...
- Android跨进程通信的四种方式
由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些.在android SDK中提供了4种用于跨进程通讯的方式.这4种方式正好对应于andro ...
- android 跨进程通信
转自:http://www.androidsdn.com/article/show/137 由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一 ...
- Android跨进程通信AIDL服务
服务(Service)是android系统中非常重要的组件.Service可以脱离应用程序运行.也就是说,应用程序只起到一个启动Service的作用.一但Service被启动,就算应用程序关闭,Ser ...
- Android跨进程通信广播(Broadcast)
广播是一种被动跨进程通讯的方式.当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据.这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通,在应用程序中发送广播比较简单.只 ...
- Android跨进程通信访问其他应用程序的Activity
访问其他应用程序的ActivityActivity既可以在进程内(同一个应用程序)访问,也可以跨进程访问.如果想在同一个应用程序中访问Activity,需要指定Context对象和Activity的C ...
- Android跨进程通信Content Provider
Content Provider ContentProvider在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通 ...
- Android跨进程通信:图文详解 Binder机制 原理
binder原理讲的很详细 https://blog.csdn.net/carson_ho/article/details/73560642
随机推荐
- 根据CPU核心数确定线程池并发线程数(转)
一.抛出问题 关于如何计算并发线程数,一般分两派,来自两本书,且都是好书,到底哪个是对的?问题追踪后,整理如下: 第一派:<Java Concurrency in Practice>即&l ...
- python多继承下的查找顺序-MRO原则演变与C3算法
在python历史版本中的演变史 python2.2之前: MRO原则: 只有经典类,遵循深度优先(从左到右)原则, 存在的问题:在有重叠的多继承中,违背重写可用原则 解决办法是再设计类的时候不要设计 ...
- C# 对象遍历 string类型 null转空字符串和去前后空格
using System; using System.Collections.Generic; namespace OA.Common.Extensions { /// <summary> ...
- 2.03_Python网络爬虫Http和Https
一:HTTP和HTTPS HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法,以明文的形式传输,效率高,但是不安全 HTTPS ...
- <meta http-equiv="X-UA-Compatible" content="IE=edge">详解
X-UA-Compatible是针对IE8新加的一个设置,对于IE8之外的浏览器是不识别的. 这个区别与content="IE=7"在无论页面是否包含<!DOCTYPE> ...
- java 项目坑记录
1. spring项目引入了lombok jar包,且已在类上面添加@Data注释,还是关联不到 get() 和 set() 方法 需要安装扩展包 如果在线安装失败,提示错误readtime out, ...
- MyBatis-06-日志
6.日志 6.1.日志工厂 如果一个数据库操作,出现了异常,我们需要排错.日志就是最好的助手! 曾经:sout.debug 现在:日志工厂 SLF4J LOG4J[掌握] LOG4J2 JDK_LOG ...
- C# 之 .net core -- 创建项目
一.新建一个Web 的 应用程序 二.选择项目的基本信息(.net coer 2.2 和带有试图控制器的程序) 这个是类似以MVC的模式,也可以用其他的,总之需要什么选什么 三. 然后既可以看到这样一 ...
- Qt disconnect函数
1. 介绍disconnect()用法 disconnect()有3种用法,其原型如下: bool QObject::disconnect(const QObject * sender, const ...
- BZOJ 2631 tree / Luogu P1501 [国家集训队]Tree II (LCT,多重标记)
题意 一棵树,有删边加边,有一条链加/乘一个数,有询问一条链的和 分析 LCT,像线段树一样维护两个标记(再加上翻转标记就是三个),维护size,就行了 CODE #include<bits/s ...