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. [转帖]VMware Converter (P2V迁移)问题汇总

    https://www.dinghui.org/vmware-converter-p2v.html VMware vCenter Converter Standalone,是一种用于将虚拟机和物理机转 ...

  2. 【转帖】ChatGPT重塑Windows!微软王炸更新:操作系统全面接入,Bing也能用插件了

    https://cloud.tencent.com/developer/article/2291078?areaSource=&traceId= 金磊 丰色 西风 发自 凹非寺 量子位 | 公 ...

  3. elementui表格内容超出显示省略号

    有些时候表格的内容太长了: 但是elementui中的表格,会进行换行处理: 此时表格的高度就会发生变化 这样就不好看,此时就要进行省略号来出来这个问题: el-table是有这个控制属性的::sho ...

  4. 【K哥爬虫普法】房产数据刑吗?爬虫多年没踩过缝纫机,劝你找找自己原因!

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识,知 ...

  5. 【JS 逆向百例】无限debugger绕过,某政民互动数据逆向

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 目标:某政务服务 ...

  6. 从零开始配置 vim(9)——初始配置

    虽然本系列文章叫做从0开始配置vim,似乎我们从一开始就要写vimrc配置文件,但是我们并没有这么做.我们先经过几篇文章了解了下面的几个内容 如何设置vim属性,从而改变vim的特征 配置快捷键,以提 ...

  7. 2.基于Label studio的训练数据标注指南:(智能文档)文档抽取任务、PDF、表格、图片抽取标注等

    文档抽取任务Label Studio使用指南 1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取).文本分类等 2.基于Label studio的训练数据标注指南:(智能文档) ...

  8. Python 多线程实现爬取图片

    前阵子网上看到有人写爬取妹子图的派森代码,于是乎我也想写一个教程,很多教程都是调用的第三方模块,今天就使用原生库来爬,并且扩展实现了图片鉴定,图片去重等操作,经过了爬站验证,稳如老狗,我已经爬了几万张 ...

  9. Python 排序与查找算法收集

    Python 语言实现几种不同的排序算法,代码来自于老男孩Python全栈开发,学习教程! import random import time import copy import sys def c ...

  10. C/C++ Npcap包实现ARP欺骗

    npcap 是Nmap自带的一个数据包处理工具,Nmap底层就是使用这个包进行收发包的,该库,是可以进行二次开发的,不过使用C语言开发费劲,在进行渗透任务时,还是使用Python构建数据包高效,唯一的 ...