Android AIDL跨进程通信
文章目录
- Android AIDL跨进程通信
- 0.我为啥要写这篇文章
- 1.AIDL是干啥的?
- 1.1简述
- 1.2官方话
- 2.在AndroidStudio中怎么干?
- 2.1准备工作
- 2.2在项目A中创建AIDL文件夹
- 2.3在项目A中创建一个aidl文件
- 2.4将项目A进行一次Rebuild操作
- 2.5在项目A中新建一个服务
- 2.6在项目A的清单文件中配置服务
- 2.7在项目B中绑定项目A的服务
- 2.7.1注意
- 2.8项目B与项目A跨进程通信的重要配置
0.我为啥要写这篇文章
(1)高版本Android系统中,AIDL通信配置上有点变化,不配置进程间通信搞不通。
1.AIDL是干啥的?
1.1简述
简单一句话讲就是两个APP之间如果要谈恋爱,就要靠AIDL来帮着搭桥牵线。
1.2官方话
AIDL是一个缩写,全程是Android Interface Definition Language,也是android接口定义语言。准确的来说,它是用于定义客户端/服务器通信接口的一种描述语言。它其实一种IDL语言,可以拿来生成用于IPC的代码。从某种意义上说它其实是一个模板。为什么这么说?因为在我们使用中,实际起作用的并不是我们写的AIDL代码,而是系统根据它生成的一个IInterface的实例的代码。而如果大家都生成这样的几个实例,然后它们拿来比较,你会发现它们都是有套路的——都是一样的流程,一样的结构,只是根据具体的AIDL文件的不同由细微变动。所以其实AIDL就是为了避免我们一遍遍的写一些前篇一律的代码而出现的一个模板。
2.在AndroidStudio中怎么干?
2.1准备工作
(1)创建好两个APP工程,以下简称项目A、项目B
(2)将项目A作为服务端,即被访问端,意思就是其他项目找项目A谈恋爱。
(3)项目B作为客户端
2.2在项目A中创建AIDL文件夹
2.3在项目A中创建一个aidl文件
(1)文件名称可以按自己的需求取
(2)文件内容其实就是一个接口,可以按自己的需求定义功能,作用其实就是服务端与客户端都遵循接口规范进行通信。
// IDevToolAidlInterface.aidl
package com.gdc.android.debug;
// Declare any non-default types here with import statements
interface IDevToolAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
2.4将项目A进行一次Rebuild操作
(1)点击AndroidStudio的Build菜单,接着点击Rebuild
(2)build完成后,在app\build\generated目录去查看自动生成的接口文件,这个接口文件非常重要,后续可以拷贝到项目B,用来与项目A进行直接通信。
2.5在项目A中新建一个服务
(1)主要用来与项目B建立通信连接,进行数据传递。
public class DevToolService extends Service {
//(1)app名称
private static final String APP_NAME = "AppName";
//(2)崩溃日志文件路径
private static final String FILEPATH = "FilePath";
private Binder binder = new IDevToolAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
};
public DevToolService() {
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
//接收项目B传递的数据
String appName = intent.getStringExtra(APP_NAME);
String filepath = intent.getStringExtra(FILEPATH);
return binder;
}
}
2.6在项目A的清单文件中配置服务
(1)即在AndroidManifest.xml中配置服务
<!--
(1)接收崩溃日志的服务
a.获取其他应用程序崩溃日志
b.将崩溃日志传递给QQ,由测试人员转发给软件开发人员
android:exported="true":表示该服务允许被跨进程使用
-->
<service
android:name="com.gdc.devtool.service.DevToolService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.gdc.devtool.service.DevToolService"/>
</intent-filter>
</service>
2.7在项目B中绑定项目A的服务
(1)在你需要进行跨进程通信的类中绑定项目A的服务,按你需求来,这里只贴绑定部分的代码。
//(a)把程序崩溃日志通过Devtool服务传给QQ
if (Constant.DEBUG_MODEL) {
Intent serviceIntent = new Intent();
serviceIntent.setPackage("com.gdc.devtool");
serviceIntent.setAction("com.gdc.devtool.service.DevToolService");
serviceIntent.putExtra(APP_NAME, FilePathManager.getAppFileRootDirectoryName());
serviceIntent.putExtra(FILEPATH, file.getAbsolutePath());
ApplicationContext.getContext().bindService(serviceIntent,serviceConnection, ApplicationContext.getContext().BIND_AUTO_CREATE);
}
(2)在ServiceConnection通信边接建立成功后,写你自己需要进行通信的内容。
private static ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//(1)成功连接
ToastUtil.show("连接成功的业务操作...");
}
@Override
public void onServiceDisconnected(ComponentName name) {
//(2)连接断开
ToastUtil.show("连接断开后的业务操作...");
}
};
2.7.1注意
(1)绑定服务的意图一定要用显示意图,这是高版本Android系统要求的,只是没调查过从哪个版本开始的。
(2)包名指的是项目A的包名,去项目A的AndroidManifest.xml顶上的package中去复制。
(3)action:也是去复制项目A中AndroidManifest.xml中服务的action配置信息。
2.8项目B与项目A跨进程通信的重要配置
(1)在Android高版本系统中,配置了上述信息之后还不够,还需要配置相关的权限
(2)在项目B中的AndroidManifest.xml中配置与项目A进行跨进程通信需要的权限信息
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission"/>
<queries>
<package android:name="com.gdc.devtool"/>
</queries>
(3)queries主要作用就是设置项目的可见性,即在项目B中可以看见项目A的包
(4)有篇博文里面是这样描述queries的
a.从Android 11 开始 系统对app的可见性进行了保护,只有部分应用可见所有app.
b.queries via package name: 标签表示只有配置了包名 才对该app可见
c.按照package的说法就是,只有配置了项目A的包名,才能看得见项目A,也才能够进行跨进程通信。