一.概述

我们可以在客户端发送一个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的更多相关文章

  1. 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇

    前言 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Andro ...

  2. android跨进程通信(IPC)——AIDL

    转载请标明出处: http://blog.csdn.net/sinat_15877283/article/details/51026711: 本文出自: [温利东的博客] 近期在看 @任玉刚 大神编写 ...

  3. Android跨进程通信的四种方式

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

  4. android 跨进程通信

    转自:http://www.androidsdn.com/article/show/137 由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一 ...

  5. Android跨进程通信AIDL服务

    服务(Service)是android系统中非常重要的组件.Service可以脱离应用程序运行.也就是说,应用程序只起到一个启动Service的作用.一但Service被启动,就算应用程序关闭,Ser ...

  6. Android跨进程通信广播(Broadcast)

    广播是一种被动跨进程通讯的方式.当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据.这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通,在应用程序中发送广播比较简单.只 ...

  7. Android跨进程通信访问其他应用程序的Activity

    访问其他应用程序的ActivityActivity既可以在进程内(同一个应用程序)访问,也可以跨进程访问.如果想在同一个应用程序中访问Activity,需要指定Context对象和Activity的C ...

  8. Android跨进程通信Content Provider

    Content Provider ContentProvider在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通 ...

  9. Android跨进程通信:图文详解 Binder机制 原理

    binder原理讲的很详细 https://blog.csdn.net/carson_ho/article/details/73560642

随机推荐

  1. linux MD5使用

    # define MD5_LONG unsigned int # define MD5_CBLOCK 64 # define MD5_LBLOCK (MD5_CBLOCK/4) # define MD ...

  2. Oracle权限管理详解(1)

    详见:https://www.cnblogs.com/yw0219/p/5855210.html Oracle 权限 权限允许用户访问属于其它用户的对象或执行程序,ORACLE系统提供三种权限:Obj ...

  3. CI/CD持续集成小结

    一.概念 什么是devops,基于Gitlab从零开始搭建自己的持续集成流水线(Pipeline) https://blog.csdn.net/chengzi_comm/article/details ...

  4. 如何自动运行loadrunner脚本

    问题背景 在凌晨之后,自然流量比较低,无需人值守的情况自动运行loadruner脚本. 实现思路 windows定时任务+BAT脚本 BAT脚本: SET M_ROOT=C:\Program File ...

  5. 2.Bacula Server端安装配置

    1.  Bacula Server端安装配置 1.1.  Bacula Server端安装 1.1.1.  安装bacula依赖包 For Centos6: yum install -y mysql ...

  6. string::back

    char& back(); const char& back() const; #include <iostream>#include <string> usi ...

  7. 题解 [51nod1673] 树有几多愁

    题面 解析 这题思路挺秒啊. 本麻瓜终于找了道好题了(还成功把ztlztl大仙拖下水了) 看到叶子节点数<=20就应该是状压啊. 然而DP要怎么写啊? 首先,考虑到编号肯定是从下往上一次增大的, ...

  8. 题解 [51nod1201] 整数划分

    题面 解析 首先,因为是不同的数字, 可以从小到大依次枚举加上每一个数字的贡献,再枚举每个数. 然而这样会T掉... 考虑到\(n\)只有\(50000\), 当分成的数最多时,设最大的数为\(m\) ...

  9. pypdf2:下载Americanlife网页生成pdf合并pdf并添加书签

    初步熟悉 安装 pip install pypdf2 合并并添加书签 #!/usr/bin/env python3.5 # -*- coding: utf-8 -*- # @Time : 2019/1 ...

  10. Verilog从文件读数据

    reg start;reg [17:0] counter;always @(posedge i_clk)//置rst.startbegin //产生读数据地址 if(counter==171519|| ...