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实现进程间通讯简单案例的更多相关文章

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

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

  2. Android 使用AIDL实现进程间的通信

    在Android中,如果我们需要在不同进程间实现通信,就需要用到AIDL技术去完成. AIDL(android Interface Definition Language)是一种接口定义语言,编译器通 ...

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

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

  4. Android(java)学习笔记232:Android进程间通讯(IPC)之AIDL

    一.IPC inter process communication  进程间通讯 二.AIDL android  interface  defination  language  安卓接口定义语言 满 ...

  5. 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 进程间 通讯 ...

  6. Android(java)学习笔记175:Android进程间通讯(IPC)之AIDL

    一.IPC inter process communication  进程间通讯 二.AIDL android  interface  defination  language  安卓接口定义语言 满 ...

  7. Android进程间通讯

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

  8. Android进程间通讯之messenger

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

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

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

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

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

随机推荐

  1. Laravel - 模板中的url

    <!-- 1, url --> <a href="{{url('/')}}">跳转到主页</a>   <!-- 2,action  方法  ...

  2. 左值,右值,引用,指针,常量,auto如何组合?

    左值,右值,引用,指针,常量,auto如何组合? 左值引用:int &a = b; 左值引用是通过使用&符号来声明的,例如int &a. 左值引用用于绑定到左值(可标识的.持久 ...

  3. Go-GC-三色标记与混合写屏障

  4. [转帖]Linux fsync和fdatasync系统调用实现分析(Ext4文件系统)

      转自:https://blog.csdn.net/luckyapple1028/article/details/61413724 在Linux系统中,对文件系统上文件的读写一般是通过页缓存(pag ...

  5. [转帖]如何用 30s 给面试官讲清楚什么是 Session-Cookie 认证

    https://www.jianshu.com/p/e1121d4d7084 引言 由于 HTTP 协议是无状态的,完成操作关闭浏览器后,客户端和服务端的连接就断开了,所以我们必须要有一种机制来保证客 ...

  6. Mac 版的 Quicker CirMenu

    之前在Windows上用过一款圆盘菜单工具Quicker, 感觉非常方便, 换成Macos后,一直没有找到类似应用. 最近终于发现,一款好用的快捷键收集,触发工具CirMenu. 其核心功能是可以根据 ...

  7. Vue基础系统文章06---导入和导出

    一.导入和导出 如果想要在一个Js文件中用另一个js文件的代码 1.将js文件中的变量和函数导出 let a = "aaaa" function show() { console. ...

  8. ABP系列文章收藏

    1.ASP.NET样板开发框架ABP系列之ABP入门教程详解: https://www.php.cn/csharp-article-380181.html 2.官网中文翻译:  https://www ...

  9. ETL之apache/hop-web 2.5安装和简单入门

    一.使用Docker 安装部署 1.拉取镜像 推荐使用下面的web版本 docker pull apache/hop:latest docker pull apache/hop-web:latest ...

  10. net core控制台程序使用依赖注入读取appsettings.json配置文件

    .net 2.1有用,转自https://www.jianshu.com/p/726d1aa2795c 1.项目下添加appsettings.json文件,并将属性-复制到输出目录,设置为如果较新则复 ...