【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中进程间通信是比较难的一部分,同时又非常 ...
随机推荐
- 【rt-thread】驱动文件调用stm32官方驱动库关系图
示例 drv_usart.c 调用 stm32f4xx_hal_uart.h
- java - 标准类的定义
一个标准的类需要拥有下面 4个 组成部分: 1. 所有的成员变量都要使用 private 关键字进行修饰 2. 为每一个成员变量编写 set.get 方法 3. 创建一个无参数的构造方法 4. 创建一 ...
- Harbor的逻辑备份与学习
Harbor的逻辑备份与学习 背景 一直想处理一下一个有网络冲突的Harbor镜像服务器 但是因为网络层自己水平一直是不是非常自信 加上Harbor容器使用的compose的玩法, 自己不敢直接处理. ...
- [转帖]Oracle中INITRANS和MAXTRANS参数
每个块都有一个块首部.这个块首部中有一个事务表.事务表中会建立一些条目来描述哪些事务将块上的哪些行/元素锁定.这个事务表的初始大小由对象的INITRANS 设置指定.对于表,这个值默认为2(索引的IN ...
- [转帖]oracle 11.2.0.4 rac集群等待事件enq: TM - contention
近期,一金融客户oracle 11.2.0.4 rac集群delete不当导致等待事件enq: TM - contention严重引起大范围会话堆积,记录的相关分析工作如下. 1.登录集群任意节点,查 ...
- [转帖]PostgreSQL 慢查询SQL跟踪
https://www.cnblogs.com/VicLiu/p/12017704.html PostgreSQL 开启慢SQL捕获在排查问题时是个很有效的手段.根据慢SQL让我在工作中真正解决了实际 ...
- [转帖]dd 自动压测与结果解析脚本
测试串行.并发.读.写 4类操作,每类操作又可以指定各种bs及count值,循环压测.每种场景一般执行3次,取平均值. 一. 串行写 #!/bin/sh bs_list=(256k 1024k 10M ...
- [转帖]011 Linux 打包与解压 tar
https://my.oschina.net/u/3113381/blog/5429977 01 压缩.打包命令有哪些? Linux 上有着各种压缩.打包的工具:tar.gzip.zip.7z,而 t ...
- ESXi 虚拟机性能情况简单验证
1.虚拟化的CPU超售问题. 经过查找资料, 发现 ESXi 5.5 的版本 一个 物理CPU的Core 可以虚拟出 25个vCPU, 升级到ESXi6.0 之后可以虚拟化32个vCPU. 所以虚拟化 ...
- 深度解析C#数组对象池ArrayPool<T>底层原理
提到池化技术,很多同学可能都不会感到陌生,因为无论是在我们的项目中,还是在学习的过程的过程,都会接触到池化技术.池化技术旨在提高资源的重复使用和系统性能,在.NET中包含以下几种常用的池化技术. (1 ...