【Android】使用AIDL实现进程间通讯简单案例
1 AIDL 简介
AIDL(Android Interface Definition Language)是一种接口定义语言,用于生成可在 Android 设备上两个进程之间进行进程间通信(IPC)的代码。通过定义编辑 adil 文件,build 后生成对应的 java 类。
如下,为定义的 MessageManager.aidl 文件经 build 后,生成的 MessageManager.java 接口的框架。该接口包含 sendMsg() 和 getMsg() 两个方法,以及一个名为 Stub 的静态抽象内部类;Stub 继承了 Binder,并实现了 MessageManager 接口,其内部定义了一个名为 Proxy 的静态内部类;Proxy 实现了 MessageManager 接口。
系统生成的 MessageManager 接口框架
服务端:MessageManager.Stub mBind = new MessageManager.Stub()
客户端:mMessageManager = MessageManager.Stub.asInterface(service)(service 是服务端传过来的Binder,即 mBind)
本文全部代码见→使用AIDL实现进程间通讯简单案例
2 项目结构

注意: aidl_C 和 aidl_S 下的 com.zhyan8.aidl 包名及其中的 aidl 文件必须一致。
3 服务端 aidl_S 代码
(1)创建 aidl 文件
MessageManager.aidl
package com.zhyan8.aidl;
interface MessageManager {
void sendMsg(String msg);
String getMsg();
}
注意:方法前不要添加 public 等修饰符。
(2)创建服务
MyService.java
package com.zhyan8.aidl_s;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.zhyan8.aidl.MessageManager;
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return mBind;
}
MessageManager.Stub mBind = new MessageManager.Stub() {
@Override
public void sendMsg(String msg) throws RemoteException {
Log.d("MyService", "客户端发来消息: " + msg);
System.out.println(msg);
}
@Override
public String getMsg() throws RemoteException {
return "abcde"; //客户端待接收的消息
}
};
}
(3)注册服务
在 AndroidManifest.xml 文件中 application 节点下注册 service,如下。
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.xxx.aidl"/>
</intent-filter>
</service>
(4)主 Activity
MainActivity.java
package com.zhyan8.aidl_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);
}
}
4 客户端 aidl_C 代码
(1)复制 aidl 文件
将 aidl_S 下的 com.zhyan8.aidl 包及其中的 aidl 文件复制到 aidl_C 中 。
(2)设计布局
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="com.zhyan8.aidl_c.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>
界面如下:

(3)主 Activity
MainActivity.java
package com.zhyan8.aidl_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;
import com.zhyan8.aidl.MessageManager;
public class MainActivity extends AppCompatActivity {
private MessageManager 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.aidl");
intent.setPackage("com.zhyan8.aidl_s");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMessageManager = MessageManager.Stub.asInterface(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);
}
}
}
注意:intent.setPackage("com.zhyan8.aidl_s") 中的 "com.zhyan8.aidl_s" 应与服务端 aidl_S 的 build.gradle 中 applicationId 属性的值一致,如下:

5 效果展示
(1)发送消息
在 EditView 中输入【Qwert】,点击【发送】按钮,在服务端可以收到发送的消息,如下:

(2)接收消息
点击【接收】按钮,客户端 aidl_C 界面可以看到服务端 aidl_S 传过来的字符串【abcde】,如下:

6 附件
以下是点击【Make Build】后自动生成的代码,路径为【aild_C\build\generated\source\aidl\debug\commu\ 】
MessageManager.java
package com.zhyan8.aidl;
public interface MessageManager extends android.os.IInterface {
public static class Default implements com.zhyan8.aidl.MessageManager {
@Override
public void sendMsg(java.lang.String msg) throws android.os.RemoteException {
}
@Override
public java.lang.String getMsg() throws android.os.RemoteException {
return null;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
public static abstract class Stub extends android.os.Binder implements com.zhyan8.aidl.MessageManager {
private static final java.lang.String DESCRIPTOR = "com.zhyan8.aidl.MessageManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.zhyan8.aidl.MessageManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.zhyan8.aidl.MessageManager))) {
return ((com.zhyan8.aidl.MessageManager) iin);
}
return new com.zhyan8.aidl.MessageManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_sendMsg: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
this.sendMsg(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getMsg: {
data.enforceInterface(descriptor);
java.lang.String _result = this.getMsg();
reply.writeNoException();
reply.writeString(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.zhyan8.aidl.MessageManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void sendMsg(java.lang.String msg) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(msg);
boolean _status = mRemote.transact(Stub.TRANSACTION_sendMsg, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().sendMsg(msg);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public java.lang.String getMsg() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getMsg, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getMsg();
}
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.zhyan8.aidl.MessageManager sDefaultImpl;
}
static final int TRANSACTION_sendMsg = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getMsg = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(com.zhyan8.aidl.MessageManager impl) {
if (Stub.Proxy.sDefaultImpl == null && impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.zhyan8.aidl.MessageManager getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public void sendMsg(java.lang.String msg) throws android.os.RemoteException;
public java.lang.String getMsg() throws android.os.RemoteException;
}
声明:本文转自【Android】使用AIDL实现进程间通讯简单案例
【Android】使用AIDL实现进程间通讯简单案例的更多相关文章
- Android AIDL 进行进程间通讯(IPC)
编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...
- Android 使用AIDL实现进程间的通信
在Android中,如果我们需要在不同进程间实现通信,就需要用到AIDL技术去完成. AIDL(android Interface Definition Language)是一种接口定义语言,编译器通 ...
- Android查缺补漏(IPC篇)-- 进程间通讯之AIDL详解
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...
- Android(java)学习笔记232:Android进程间通讯(IPC)之AIDL
一.IPC inter process communication 进程间通讯 二.AIDL android interface defination language 安卓接口定义语言 满 ...
- 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 进程间 通讯 ...
- Android(java)学习笔记175:Android进程间通讯(IPC)之AIDL
一.IPC inter process communication 进程间通讯 二.AIDL android interface defination language 安卓接口定义语言 满 ...
- Android进程间通讯
最近研究了一下Android进程间通讯,原来只是会用,但是只是会用是不行滴,就来研究一下. 刚开始看的时候,我的头是这么大,看了一夜的时候,头就变成这样了,,吓得宝宝赶紧上床休息了,. 先喝喝茶讲个故 ...
- Android进程间通讯之messenger
这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下. 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都 ...
- Android进阶笔记04:Android进程间通讯(IPC)之Messenger
一. Android进程间通讯之Messenger 的引入 (1)引言: 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...
- Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...
随机推荐
- [转帖]直接内存监控不准确,netty玩了什么花?
https://segmentfault.com/a/1190000044509636 是挺久没有"宠爱"我们netty小婊贝了,最近又开始搞事了. 于是,趁机探究了下MX ...
- [转帖]SQL Server中查询CPU占用高的SQL语句
本文导读:触发器造成死锁.作业多且频繁.中间表的大量使用.游标的大量使用.索引的设计不合理.事务操作频繁.SQL语句设计不合理,都会造成查询效率低下.影响服务器性能的发挥.我们可以使用sql serv ...
- Tidb 使用minio 进行br备份数据库的过程
Tidb 使用minio 进行br备份数据库的过程 背景 br 备份恢复时一般需要共享存储. 前段时间一直使用的是nfs 进行共享文件备份. 这样需要所有的机器在 相同的目录下面挂载相同的nfs. 并 ...
- [转帖]DBWR与LGWR的写入机制
https://www.jianshu.com/p/6c87cb6cd320 读与写是每个数据库提供的最基本的功能.当数据库中出现第一个进程时,总免不了要将数据从磁盘上加载到内存中,一次数据库的物理I ...
- [转帖]Kafka 与RocketMQ 落盘机制比较
https://www.jianshu.com/p/fd50befccfdd 引言 前几期的评测中,我们对比了Kafka和RocketMQ的吞吐量和稳定性,本期我们要引入一个新的评测标准--软件可靠性 ...
- [转帖]如何提高Linux下块设备IO的整体性能?
http://www.yunweipai.com/6989.html 运维派隶属马哥教育旗下专业运维社区,是国内成立最早的IT运维技术社区,欢迎关注公众号:yunweipai领取学习更多免费Linux ...
- [转帖]Linux命令学习手册-readelf
https://www.jianshu.com/p/405844abefae readelf elf-file(s) 功能 用于显示 elf 格式文件的信息. 描述 readelf 用来显示一个或者多 ...
- PG数据库异步流复制
PG数据库异步流复制 背景说明 最近想进行一个数据库高可用课题的研究. 因为之前某种原因,这次选择的是PG数据库. 为了简单起见, 暂时采用PG异步流复制的场景. 这次仅是为了测试, 不考虑高可用绿色 ...
- 在Linux Ubuntu系统中部署C++环境与Visual Studio Code软件
本文介绍在Linux Ubuntu操作系统下,配置Visual Studio Code软件与C++代码开发环境的方法. 在文章VMware虚拟机部署Linux Ubuntu系统的方法中,我们介 ...
- KubeSphere2.1踩坑记
至少两台机器.推荐4X16.(完全安装KubeSphere会吃掉10G+内存) k8s安装(略1.14.8)可参考我上一篇文章或者基于kubeadmin快速安装 KubeSphere2.1前置条件 1 ...