AIDL 最广泛与最简单的应用是与四大组件之一 Serivce 的配合使用了。我们都知道,启动一个 Serivce 有两种方式:1、通过 startService 的方式;2、通过 bindService 的方式。 通过 binService 方式启动的 Service 所返回的对象类型,就可以理解为是 AIDL 跨进程通信类型。
一.服务端
首先创建一个服务端的apk项目,创建AIDL文件.
创建完成后结构如下:
可以看到AIDL文件所在的包和java包路径是一致的.
根据业务需求修改所创建的aidl文件.
package com.example.myserver;
// Declare any non-default types here with import statements
interface myhonaidl {
String getInfo(String info);
}
接着创建对应的service.
package com.example.myserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class HonService extends Service {
public HonService() {
}
//重点步骤,用来实现接口
public class MyBinder extends myhonaidl.Stub{
@Override
public String getInfo(String info) throws RemoteException {
return xxxxx;
}
}
//重点 记得返回实现接口的对象
@Override
public IBinder onBind(Intent intent) {
Log.e("HonService","onBind");
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
Log.e("HonService","onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("HonService","onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.e("HonService","onDestroy");
super.onDestroy();
}
注意:这里有个坑会导致自己创建service无法导入定义的aidl文件接口.
解决办法如下:
在module即带编译版本的build.gradle加上如下,用来给AS指路.
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
注意:做完这步记得Make project
到此服务端apk初步搞定.
二.客户端
新建module或者项目,参照服务端aidl,最好直接拷贝过来,要一一对应.
其实客户端这边只需要绑定服务端service即可,核心代码如下:
//用来开启服务端service
Intent mIntent = new Intent(Intent.ACTION_MAIN);
ComponentName componentName = new ComponentName(
"包名",
"对应服务类名");
mIntent.setComponent(componentName);
boolean result = bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
private myhonaidl its;//导包和服务端相同
private ServiceConnection mServiceConnection =new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.e("MainActivity","=====onServiceConnected===");
its=myhonaidl.Stub.asInterface(iBinder);
try {
String test=its.getInfo("xxx");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e("MainActivity","=====onServiceDisconnected===");
}
};
注意:targetSdk 版本为30的时候,在Android11 的机型上,AIDL完全不可用,服务也连接不上,但是在低版本的手机上,或者targetSdk 29时候可以用.
解决办法:在清单文件添加对应根节点
<queries>
<package android:name="需要开启服务的apk包名" />
</queries>
管理软件包可见性 | Android 开发者 | Android Developers //官方API参考