文章目录
概要
阅读本文前提:了解binder机制以及跨进程通信的知识点,能实现普通的App添加AIDL接口并调用。
在普通App开发中,我们在Android studio中可以直接创建,如下
然后编译一下整个项目,相关的AIDL就会生成对应的Java文件,项目中就可以使用这个接口了。但是在AOSP系统应用中,我们定义好AIDL文件,怎么才能让系统识别并编译这个文件呢?
实现过程
以launcher3应用为例:在该应用中添加一个AIDL接口(获取桌面默认app功能)
1、创建AIDL文件及其服务端代码
在src/com.android.launcher3路径下,新建一个ICustomerAppsInterface.aidl,同时新建对应的服务端CustomAppsService.java,如下:
(1)其中AIDL文件内容如下:
// ICustomerAppsInterface.aidl
package com.android.launcher3;
// Declare any non-default types here with import statements
interface ICustomerAppsInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
List<String> getOriginApps();
}
(2)对应的服务端代码如下:
package com.android.launcher3;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import java.util.ArrayList;
import java.util.List;
public class CustomerAppsService extends Service {
private String TAG = "CustomerAppsService";
private final ICustomerAppsInterface.Stub binder = new ICustomerAppsInterface.Stub(){
@Override
public List<String> getOriginApps(){
List<String> retList = new ArrayList<>();
retList.add("hello");
retList.add("world");
return retList;
}
};
@Override
public void onCreate() {
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
2、把AIDL添加到项目的Android编译脚本中!!!!!
重点来了,要想项目识别并编译新建的AIDL,需要把这个文件添加到编译脚本中,我用的是Android13的版本,对应的launcher编译脚本是framework/packages/apps/Launcher3/Android.bp
如图所示:在launcher-src模块中添加aidl的源码,这样自定义的AIDL就能参与项目编译了
3、Launcher项目AndroidManifest.xml添加服务
把我们写的服务端service添加到安卓清单中
4、编译AOSP源码或者单编Launcher项目
经过上面的步骤,我们已经在AOSP系统应用中添加好了AIDL接口及其服务,编译整个项目刷机,或者单编应用成APK在运行均可。
5、普通应用调用该接口与系统应用通信
(1)AS创建新应用
略过
(2)添加AIDL接口
在模块main中,创建aidl文件夹,把上面定义的ICustomerAppsInterface.aidl及其完整的包拷贝到该目录中,如下所示:
接着在编译一下项目,该aidl文件就会生成对应的java文件:
这样,我们在项目中就可以使用该接口了
(3)绑定AIDL服务并通信
来到项目app模块,onCreate()中添加绑定服务:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 定义intent
Intent intent = new Intent();
intent.setAction("android.intent.action.customerApps");
intent.setPackage("com.android.launcher3");
bindService(intent, mConnection, Context.BIND_AUTO_CREATE); // 绑定服务!!!
// 屏幕上的按钮
mButton = findViewById(R.id.btn_aidl);
// 按钮点击事件
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "onClick: btn click");
try {
// 绑定成功后,这里就可以利用appsInterface(AIDL客户端)取出我们在Launcher项目中数据啦
List<String> originApps = appsInterface.getOriginApps();
for (String s: originApps){
Log.d(TAG, "onServiceConnected: " + s);
}
}catch (Exception e){
Log.d(TAG, "onServiceConnected: " + e.getMessage());
e.printStackTrace();
}
}
});
}
其中mConnection如下:
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获取AIDL的客户端
appsInterface = ICustomerAppsInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
appsInterface = null;
}
};
(4)Android高版本服务绑定无效
SDK30以上的版本,bindService()无效:主要是谷歌对绑定其他应用的服务做了严格的限制。
参看这篇文章:https://blog.csdn.net/fengyeNom1/article/details/123250141
按照文中的说法,要么降版本到30以下,要么app的安卓清单中添加标签:
小结
两个普通的app通过AIDL通信,大家都不陌生,本文主要介绍AIDL服务端定义在系统应用中,怎么编译这个AIDL的问题
其实就是去对应的Android.bp/mk中添加该AIDL资源文件,再编译即可。
最后:文中如有错误或者补充,欢迎大家指正~。