1 前言

使用AIDL实现进程间通讯简单案例使用AIDL实现进程间传递对象案例 中介绍了使用 AIDL 进行进程间通讯,文中提到在编写完 aidl 文件(如:IMessageManager.aidl)并 Make Buidl 后,会生成一个接口(如:IMessageManager.java),接口中包含一个静态抽象内部类 Stub,Stub 中又包含一个静态内部类 Proxy,Stub 和 Proxy 都实现了此接口,同时 Stub 继承了 Binder 类。本文将从 IMessageManager 接口中剥离 Stub(用于服务端) 和 Proxy(用于客户端),使读者更深刻的理解 AIDL 和 Binder,如下。

​ 说明:左边 Stub 为抽象类,无需重写 sendMsg、getMsg,右边 Stub 为具体类,需要重写 sendMsg、getMsg。

(1)AIDL中生成服务端与客户端

​ 服务端:IMessageManager.Stub mBind = new MessageManager.Stub()

​ 客户端:mMessageManager = IMessageManager.Stub.asInterface(service)(service 是服务端传过来的Binder,即 mBind)

(2)本文中生成服务端与客户端

​ 服务端:Stub mBind = new Stub()

​ 客户端:mMessageManager = new Proxy(service)(service 是服务端传过来的Binder,即 mBind)

​ 本文全部代码见→使用Binder实现进程间通讯简单案例

2 Binder 简介

​ Binder 翻译即粘合剂,是客户端和服务端沟通的桥梁,用于进程建通讯。Binder 的主要属性和方法如下:

​ 在 transact 方法中调用了 onTransact,如下:

public final boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}

​ 使用 Binder 进行进程间通讯时,需要做以下工作:

(1)Stub 类(服务端创建 Binder的子类)

  • Stub extends Binder implements IMessageManager
  • 构造方法中调用 this.attachInterface(this, DESCRIPTOR)
  • asBinder 方法返回 this
  • 重写 IMessageManager 接口中的方法
  • 重写 Binder 的 onTransact 方法

(2)Proxy 类(客户端接受 Binder,并对其进行封装)

  • Proxy implements IMessageManager
  • 构造方法接受 Binder:mRemote = remote
  • asBinder 方法返回 mRemote
  • 重写 IMessageManager 接口中的方法,调用 mRemote.transact(code, data, reply, 0)

3 项目结构

4 服务端 binder_S 代码

​ IMessagManager.java

package com.zhyan8.binder_s;

import android.os.IInterface;
import android.os.RemoteException; public interface IMessageManager extends IInterface {
public void sendMsg(String msg) throws RemoteException;
public String getMsg() throws RemoteException;
}

​ Stub.java

package com.zhyan8.binder_s;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log; public class Stub extends Binder implements IMessageManager {
private final String DESCRIPTOR = "com.yyy.binder";
private final int TRANSACTION_sendMsg = IBinder.FIRST_CALL_TRANSACTION;
private final int TRANSACTION_getMsg = IBinder.FIRST_CALL_TRANSACTION + 1; public Stub(){
this.attachInterface(this, DESCRIPTOR);
} @Override
public IBinder asBinder() {
return this;
} @Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case TRANSACTION_sendMsg:
data.enforceInterface(DESCRIPTOR);
String msg = data.readString();
this.sendMsg(msg);
reply.writeNoException();
return true;
case TRANSACTION_getMsg:
data.enforceInterface(DESCRIPTOR);
String _result = this.getMsg();
reply.writeNoException();
reply.writeString(_result);
return true;
}
return super.onTransact(code, data, reply, flags);
} @Override
public void sendMsg(String msg) throws RemoteException {
Log.d("MyService", "客户端发来消息: " + msg);
System.out.println(msg);
} @Override
public String getMsg() throws RemoteException {
return "abcde"; //客户端待接收的消息
}
}

​ 注意:DESCRIPTOR 取值必须和 Proxy 中一致。

​ MyService.java

package com.zhyan8.binder_s;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder; public class MyService extends Service { @Override
public IBinder onBind(Intent intent) {
return mBind;
} Stub mBind = new Stub();
}

​ 在 AndroidManifest.xml 中配置服务如下:

<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.xxx.binder"/>
</intent-filter>
</service>

​ MainActivity.java

package com.zhyan8.binder_s;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

5 客户端 binder_C 代码

​ IMessagManager.java 同第 4 节。

​ Proxy.java

package com.zhyan8.binder_c;

import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException; public class Proxy implements IMessageManager {
private IBinder mRemote;
private final String DESCRIPTOR = "com.yyy.binder";
private final int TRANSACTION_sendMsg = IBinder.FIRST_CALL_TRANSACTION;
private final int TRANSACTION_getMsg = IBinder.FIRST_CALL_TRANSACTION + 1; Proxy(IBinder remote) {
mRemote = remote;
} @Override
public IBinder asBinder() {
return mRemote;
} @Override
public void sendMsg(String msg) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(DESCRIPTOR);
data.writeString(msg);
mRemote.transact(TRANSACTION_sendMsg, data, reply, 0);
reply.readException();
} finally {
reply.recycle();
data.recycle();
}
} @Override
public String getMsg() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
String result;
try {
data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(TRANSACTION_getMsg, data, reply, 0);
reply.readException();
result = reply.readString();
} finally {
reply.recycle();
data.recycle();
}
return result;
}
}

​ 注意:DESCRIPTOR 取值必须和 Stub 中一致。

​ MainActivity.java

package com.zhyan8.binder_c;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView; public class MainActivity extends AppCompatActivity {
private Proxy mMessageManager;
private EditText et_msg;
private Button btn_send;
private TextView tv_msg;
private Button btn_recv; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
} public void init() {
et_msg = (EditText) findViewById(R.id.et_msg);
btn_send = (Button) findViewById(R.id.btn_send);
tv_msg = (TextView) findViewById(R.id.tv_msg);
btn_recv = (Button) findViewById(R.id.btn_recv);
btn_send.setOnClickListener(cl);
btn_recv.setOnClickListener(cl);
} View.OnClickListener cl = new View.OnClickListener(){
@Override
public void onClick(View v) {
if (v.getId()==R.id.btn_send) {
String str = et_msg.getText().toString();
sendMsg(str);
}else if(v.getId()==R.id.btn_recv) {
String str = getMsg();
tv_msg.setText(str);
}
}
}; private void sendMsg(String str){
if (mMessageManager==null) {
attemptToBindService();
}
try {
mMessageManager.sendMsg(str);
} catch (RemoteException e) {
e.printStackTrace();
}
} private String getMsg(){
if (mMessageManager==null) {
attemptToBindService();
}
try {
String str = mMessageManager.getMsg();
return str;
} catch (RemoteException e) {
e.printStackTrace();
}
return "";
} private void attemptToBindService() {
Intent intent = new Intent();
intent.setAction("com.xxx.binder");
intent.setPackage("com.zhyan8.binder_s");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
} ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMessageManager = new Proxy(service);
} @Override
public void onServiceDisconnected(ComponentName name) {
mMessageManager = null;
}
}; @Override
protected void onStart() {
super.onStart();
if (mMessageManager==null) {
attemptToBindService();
}
} @Override
protected void onStop() {
super.onStop();
if (mMessageManager!=null) {
unbindService(conn);
}
}
}

​ activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity"> <EditText
android:id="@+id/et_msg"
android:layout_width="match_parent"
android:layout_height="100dp"
android:textSize="30sp"
android:background="#ffcc66"/> <Button
android:id="@+id/btn_send"
android:layout_width="match_parent"
android:layout_height="80dp"
android:text="发送"
android:textSize="30sp"
android:layout_marginTop="30dp"/> <TextView
android:id="@+id/tv_msg"
android:layout_width="match_parent"
android:layout_height="100dp"
android:textSize="30sp"
android:background="#ffcc66"
android:layout_marginTop="50dp"/> <Button
android:id="@+id/btn_recv"
android:layout_width="match_parent"
android:layout_height="80dp"
android:text="接收"
android:textSize="30sp"
android:layout_marginTop="30dp"/>
</LinearLayout>

​ 界面如下:

6 效果展示

(1)发送消息

​ 在 EditView 中输入【asdfg】,点击【发送】按钮,在服务端可以收到发送的消息,如下:

(2)接收消息

​ 点击【接收】按钮,客户端 binder_C 界面可以看到服务端 binder_S 传过来的字符串【abcde】,如下:

​ 声明:本文转自【Android】使用Binder实现进程间通讯简单案例

【Android】使用Binder实现进程间通讯简单案例的更多相关文章

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

    本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...

  2. Android Binder 进程间通讯机制梳理

    什么是 Binder ? Binder是Android系统中进程间通讯(IPC)的一种方式,也是Android系统中最重要的特性之一.Binder的设计采用了面向对象的思想,在Binder通信模型的四 ...

  3. android 进程间通信 messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯? android 消息机制 进程间 android 进程间 可以用 handler么 messenger 与 handler 机制 messenger 机制 是不是 就是 handler 机制 或 , 是不是就是 消息机制 android messenge

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯 ...

  4. Android进程间通讯

    最近研究了一下Android进程间通讯,原来只是会用,但是只是会用是不行滴,就来研究一下. 刚开始看的时候,我的头是这么大,看了一夜的时候,头就变成这样了,,吓得宝宝赶紧上床休息了,. 先喝喝茶讲个故 ...

  5. Android进程间通讯之messenger

    这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下. 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都 ...

  6. Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...

  7. Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8387752.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  8. Android查缺补漏(IPC篇)-- 进程间通讯之AIDL详解

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

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

    编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...

  10. Android进阶笔记04:Android进程间通讯(IPC)之Messenger

    一. Android进程间通讯之Messenger 的引入 (1)引言:      平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...

随机推荐

  1. [python]使用标准库logging实现多进程安全的日志模块

    前言 原本应用的日志是全部输出到os的stdout,也就是控制台输出.因其它团队要求也要保留日志文件,便于他们用其他工具统一采集,另一方面还要保留控制台输出,便于出问题的时候自己直接看pod日志.具体 ...

  2. 百度网盘(百度云)SVIP超级会员共享账号每日更新(2023.11.23)

    一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...

  3. blender 3D 汽车模型下载

    前言 因为之前需要模拟摄像头拍摄汽车车牌,从各种途径下载了一些blender 3D 汽车模型,现将模型分享出来,如有需要,直接去最后面下载地址下载即可 目前已经车型40多款 车型图 70年代Porsc ...

  4. [转帖]nginx中的if和else语法

    https://www.dyxmq.cn/it/nginx/nginx-if.html nginx支持if语法,语法和平常的代码格式差不多:   1 2 3 if ($xxx = xxx) {     ...

  5. [转帖]oracle 11g 分区表创建(自动按年、月、日分区)

    https://www.cnblogs.com/yuxiaole/p/9809294.html   前言:工作中有一张表一年会增长100多万的数据,量虽然不大,可是表字段多,所以一年下来也会达到 1G ...

  6. 【图】苹果Safari 6.0停止支持Windows PC (转载)

    [图]果Safari 6.0停止支持Windows PC (转载) http://bbs.tianya.cn/post-414-41510-1.shtml 2012年之后 苹果就不在开发 window ...

  7. PG数据库异步流复制

    PG数据库异步流复制 背景说明 最近想进行一个数据库高可用课题的研究. 因为之前某种原因,这次选择的是PG数据库. 为了简单起见, 暂时采用PG异步流复制的场景. 这次仅是为了测试, 不考虑高可用绿色 ...

  8. TypeScript 类型增强declare的使用

    类型增强 declare 的使用 1.如果一个有一个全局变量 golabaol . 在index.html中. 2.我们在xx.vue中使用 golabaol .这个时候会报错 找不到名称" ...

  9. 【JS 逆向百例】有道翻译接口参数逆向

    逆向目标 目标:有道翻译接口参数 主页:https://fanyi.youdao.com/ 接口:https://fanyi.youdao.com/translate_o?smartresult=di ...

  10. gym.spaces中找不到prng解决方案

    gym.spaces中找不到prng解决方案 在运行飞桨MADDPG问题是遇到模型无法导入不存的的问题: ModuleNotFoundError: No module named 'multiagen ...