- 环境搭建
build.gradle
android {
//引用ADIL
buildFeatures {
aidl = true
}
}
然后点击File -> new -> AIDL ->AIDL FILE

- 创建AIDL
AIDL包名结构

CarProperty.aidl
package com.kx.aidl;
//数据回调和传输类,必现实现Parcelable
parcelable CarProperty;
CarProperty.java
package com.kx.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class CarProperty implements Parcelable {
public int property;
public int value;
//out使用
public CarProperty() {
}
public CarProperty(int propertyId, int value) {
this.property = propertyId;
this.value = value;
}
protected CarProperty(Parcel in) {
property = in.readInt();
value = in.readInt();
}
public static final Creator<CarProperty> CREATOR = new Creator<CarProperty>() {
@Override
public CarProperty createFromParcel(Parcel in) {
return new CarProperty(in);
}
@Override
public CarProperty[] newArray(int size) {
return new CarProperty[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(property);
dest.writeInt(value);
}
//inout使用
public void readFromParcel(Parcel in) {
// 按顺序读取字段,和 writeToParcel() 一致
this.property = in.readInt();
this.value = in.readInt();
}
@Override
public String toString() {
return "CarProperty{" +
"property=" + property +
", value=" + value +
'}' + super.toString();
}
}
CarPropertyCallBack.aidl
package com.kx.aidl;
import com.kx.aidl.CarProperty;
//数据回调接口,客户端传该类给服务端,服务端通过调用该接口传数据给客户端
interface CarPropertyCallBack {
void onCarPropertyCallBack(in CarProperty carProperty);
}
ICarServiceManager.aidl
package com.kx.aidl;
import com.kx.aidl.CarPropertyCallBack;
import com.kx.aidl.CarProperty;
/**
*
* 客户端的AIDL文件里面的方法位置必现和服务端一致,不然会抛异常
*
* 修饰符 客户端值传给服务端 服务端修改是否影响客户端
* in ✅ 是 ❌ 否
* out ❌ 否 ✅ 是(返回时一次)
* inout ✅ 是 ✅ 是(返回时一次)
*
*/
interface ICarServiceManager {
//基本类型(如 int、boolean、float 等)默认是 in,不能声明为 out 或 inout
//如果 AIDL 方法是典型的 setter 形式(void setXxx(...)),
//并且客户端完全不关心这次调用是否成功/异常,
//那么应该加上 oneway,让客户端立即返回,不阻塞。
//在 AIDL 中,只要方法被标记为 oneway,它就不能再声明任何 out 或 inout 参数,
//只能全部是 in 参数(或者干脆没有任何参数)。
oneway void setCarProperty(int property, int value);
int getCarProperty(int property);
List<CarProperty> getCarPropertyBean(int property);
oneway void addCarPropertyCallBack(CarPropertyCallBack carPropertyCallBack, in int[]signals);
//in只传值给服务端,服务端值改变,客户端值不变
//客户端将数据类传过去,服务端新建一个类拷贝客户端的数据,服务端操作的是服务端的类,所有只会传值
//客户端和服务端互补干扰
//会接收客户端数据类的但是不会修改客户端的值
oneway void inCarProperty(in CarProperty property);
//客户端的值无法传递过去。服务端会新建一个类,然后在服务端修改这个类的值,
//然后修改客户端的传过去的类的值,调用后客户端数据类会同步服务端的修改,值和服务端一样
//不会接收(客户端传进来的值会被忽略)
//会修改一次(服务端方法返回时,把新值写回客户端)
//服务端需要输出一个值给客户端,但不需要客户端输入
//不会接收客户端数据类传过去的值,并且在服务端该方法解释后会修改一次客户端该数据类的值
void outCarProperty(out CarProperty property);
//客户端传给服务端的值,服务端能收到,并且服务端能修改客户端的值,能改变客户端的值
//并且只能改变一次该值,在服务端方法结束后修改客户端的值,且只在这里修改一次
void inOutCarProperty(inout CarProperty property);
}
- 创建服务
CarService.java
package com.kx.client;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import com.kx.aidl.CarProperty;
import com.kx.aidl.CarPropertyCallBack;
import com.kx.aidl.ICarServiceManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class CarService extends Service {
public static final String TAG = "CarService_kx_CarService";
private Map<Integer, HashSet<Integer>> signalsMap = new HashMap<>();
private final static Object lock = new Object();
private final HashSet<String> permissionSet = new HashSet<>();
private final Handler handler = new Handler(Looper.getMainLooper());
private final List<CarPropertyCallBack> carPropertyCallBackList = new ArrayList<>();
private int value;
private CarProperty carProperty = new CarProperty(70, 70);
private final List<DeathRecipientService> deathRecipientServiceList = new ArrayList<>();
private final ICarServiceManager.Stub mBinder = new ICarServiceManager.Stub() {
@Override
public void setCarProperty(int property, int value) throws RemoteException {
checkCaller();
Log.d(TAG, "setCarProperty property1 " + property + " value " + value);
CarService.this.value = value;
handler.postDelayed(new Runnable() {
@Override
public void run() {
CarProperty carProperty = new CarProperty(property, value);
try {
Log.d(TAG, "getCarProperty property1 " + property + " value " + value);
for (CarPropertyCallBack carPropertyCallBack : carPropertyCallBackList) {
carPropertyCallBack.onCarPropertyCallBack(carProperty);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}, 1000);
}
@Override
public int getCarProperty(int property) throws RemoteException {
Log.d(TAG, "getCarProperty property1 " + property + " value " + value);
return CarService.this.value;
}
@Override
public List<CarProperty> getCarPropertyBean(int property) throws RemoteException {
return null;
}
/**
* 修饰符 客户端值传给服务端 服务端修改是否影响客户端
* in ✅ 是 ❌ 否
* out ❌ 否 ✅ 是(返回时一次)
* inout ✅ 是 ✅ 是(返回时一次)
*
*/
@Override
public void inCarProperty(CarProperty property) throws RemoteException {
property.value++;
property.property++;
Log.d(TAG, "CarPropertyBack Service in " + property.toString());
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "CarPropertyBack Service delayed in " + property.toString());
}
}, 1000);
}
/**
* 修饰符 客户端值传给服务端 服务端修改是否影响客户端
* in ✅ 是 ❌ 否
* out ❌ 否 ✅ 是(返回时一次)
* inout ✅ 是 ✅ 是(返回时一次)
*
*/
@Override
public void outCarProperty(CarProperty property) throws RemoteException {
property.value++;
property.property++;
Log.d(TAG, "CarPropertyBack Service out " + property.toString());
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "CarPropertyBack Service delayed out " + property.toString());
}
}, 1000);
}
/**
* 修饰符 客户端值传给服务端 服务端修改是否影响客户端
* in ✅ 是 ❌ 否
* out ❌ 否 ✅ 是(返回时一次)
* inout ✅ 是 ✅ 是(返回时一次)
*
*/
@Override
public void inOutCarProperty(CarProperty property) throws RemoteException {
property.value++;
property.property++;
Log.d(TAG, "CarPropertyBack Service inOut " + property.toString());
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "CarPropertyBack Service delayed inOut " + property.toString());
property.value = property.value + 10;
property.property = property.property + 10;
Log.d(TAG, "CarPropertyBack Service delayed1 inOut " + property.toString());
}
}, 1000);
// inout 参数的含义是:
// 客户端把值传给服务端;
// 服务端可以读取并修改这个值;
// 服务端返回时,修改后的值会回传给客户端;
// 但只回传一次,即服务端返回时那一次。
// AIDL 不是共享内存模型,服务端对 inout 参数的修改不会实时同步到客户端。只有在服务端方法返回时,修改才会一次性写回客户端。
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
// isWhiteList(getCallingUid());
return super.onTransact(code, data, reply, flags);
}
@Override
public void addCarPropertyCallBack(CarPropertyCallBack carPropertyCallBack, int[] signals) throws RemoteException {
//加锁,避免多线程同时进来导致反复添加
synchronized (CarService.lock) {
//白名单判断
isWhiteList(getCallingUid());
if (!carPropertyCallBackList.contains(carPropertyCallBack)) {
HashSet<Integer> hashSet = Arrays.stream(signals)
.boxed()
.collect(Collectors.toCollection(HashSet::new));
signalsMap.put(carPropertyCallBack.hashCode(), hashSet);
//创建监听,同时将回调保存到服务端
new DeathRecipientService(carPropertyCallBack, CarService.this);
Log.d(TAG, "addCarPropertyCallBack add " + carPropertyCallBack);
} else {
Log.d(TAG, "addCarPropertyCallBack exist " + carPropertyCallBack);
}
}
}
};
/**
* 注册监听服务限制,通过uid拿到packageName,如果在白名单内才允许下发
*
* @param uid
* @return true:白名单内,false:不在白名单
*/
private boolean isWhiteList(int uid) {
String[] packages = getPackageManager().getPackagesForUid(uid);
if (packages == null || packages.length == 0) return false;
String callerPkg = packages[0];
//只需要插叙的,使用HashSet,通过哈希表 平均 O(1)
if (permissionSet.contains(callerPkg)) {
Log.d(TAG, "onBind callerPkg " + callerPkg);
return true;
} else {
Log.w(TAG, "onBind 非法包名:" + callerPkg);
return false;
}
}
public List<DeathRecipientService> getDeathRecipientServiceList() {
return deathRecipientServiceList;
}
public List<CarPropertyCallBack> getCarPropertyCallBackList() {
return carPropertyCallBackList;
}
/**
* 客户端监听,客户端崩溃后异常客户端注册的binder,避免内存溢出
*/
private static class DeathRecipientService implements IBinder.DeathRecipient {
private IBinder binder;
private CarPropertyCallBack callBack;
private CarService carService;
public DeathRecipientService(CarPropertyCallBack callBack, CarService carService) {
this.binder = callBack.asBinder();
this.callBack = callBack;
this.carService = carService;
try {
binder.linkToDeath(this, 0);
//注册异常崩溃回调成功过后,保存对应回调
carService.getDeathRecipientServiceList().add(this);
//保存客户端回调函数
carService.getCarPropertyCallBackList().add(callBack);
Log.d(TAG, "客户端回调 注册回调:" + callBack +
" size " + carService.getDeathRecipientServiceList().size());
} catch (RemoteException e) {
e.printStackTrace();
//注册异常,参数置空
this.binder = null;
this.callBack = null;
this.carService = null;
Log.e(TAG, "RemoteException " + e);
}
}
@Override
public void binderDied() {
if (binder != null) {
//客户端异常过后,异常注册的回调,移除保存项,同时置空保存的所有类
carService.getDeathRecipientServiceList().remove(this);
carService.getCarPropertyCallBackList().remove(callBack);
Log.d(TAG, "客户端回调 移除回调:" + callBack +
" size " + carService.getDeathRecipientServiceList().size());
binder.unlinkToDeath(this, 0);
this.callBack = null;
binder = null;
carService = null;
}
}
}
@Override
public void onCreate() {
super.onCreate();
permissionSet.add("com.kx.customview");
Log.d(TAG, "CarService onCreate");
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "IBinder onBind");
return mBinder;
}
/**
* 检查当前调用的在不在白名单里面,不在白名单抛异常
*/
private void checkCaller() {
int uid = Binder.getCallingUid();
String[] packages = getPackageManager().getPackagesForUid(uid);
if (packages == null || packages.length == 0) return ;
String callerPkg = packages[0];
//只需要插叙的,使用HashSet,通过哈希表 平均 O(1)
if (permissionSet.contains(callerPkg)) {
Log.d(TAG, "onBind callerPkg " + callerPkg);
} else {
Log.w(TAG, "onBind 非法包名:" + callerPkg);
throw new SecurityException("Access denied");
}
}
}
AndroidManifest.xml注册
<service
android:name=".CarService"
android:enabled="true"
android:exported="true"
android:process=":remote"> <!-- 独立进程 -->
<intent-filter>
<action android:name="com.kx.client.CarService" />
</intent-filter>
</service>
- 创建客户端服务类
CarServiceManager.java
package com.kx.aidl;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class CarServiceManager {
public static final String TAG = "CarService_kx_CarServiceManger";
public static final String PACKAGE_NAME = "com.kx.client";
public static final String CLASS_NAME = "com.kx.client.CarService";
private volatile static CarServiceManager instance;
private ICarServiceManager carServiceManager;
private boolean bind;
private CarPropertyCallBack carPropertyCallBack;
private Context context;
private ConnectListener connectListener;
private int[] feedbackSignals;
/**
* 重连时间
*/
private static final int RECONNECT_HEARTBEAT = 1000;
/**
* 重连次数
*/
private static final int RECONNECT_TIME = 60;
private final Object mLock = new Object();
/**
* 重连次数
*/
private int mConnectionRetryCount = 0;
/**
* 重连的时候开启新的线程
*/
private HandlerThread handlerThread;
private Handler reconnectHandler;
/**
* 重连新线程回调
*/
private final Runnable reconnectRunnable = new Runnable() {
@Override
public void run() {
startReconnect();
}
};
/**
* 断线回调机制,service.linkToDeath(deathRecipient, 0)注册回调后,在服务器异常销毁
* 的时候会执行该方法
*/
private final IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.d(TAG, "服务端异常,准备重连...");
synchronized (CarServiceManager.this.mLock) {
if (carServiceManager != null) {
//接收到异常销毁的时候解除监听,避免内存异常
carServiceManager.asBinder().unlinkToDeath(deathRecipient, 0);
carServiceManager = null;
bind = false;
//分发出去,该服务绑定失败
if (connectListener != null) {
connectListener.onConnect(bind);
}
}
//初始化重连
initReconnect();
}
}
};
/**
* 创建binder回调 ServiceConnection
*/
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "ServiceConnection bind " + service);
//binder成功后,移除重新bind的线程,
closeReconnect();
if (feedbackSignals != null) {
//获取bind成功后的binder
carServiceManager = ICarServiceManager.Stub.asInterface(service);
try {
//注册监听,监听服务端是否异常退出,异常退出开始循环获取
service.linkToDeath(deathRecipient, 0);
//注册回调接口,服务台通过该接将数据传给客户端
carServiceManager.addCarPropertyCallBack(carPropertyCallBackLocation, feedbackSignals);
Log.d(TAG, "ServiceConnection bind true ");
bind = true;
} catch (RemoteException e) {
e.printStackTrace();
Log.d(TAG, "ServiceConnection bind Exception " + e);
bind = false;
}
} else {
Log.d(TAG, "ServiceConnection feedback Signals is empty ");
bind = false;
}
//分发bind情况
if (connectListener != null) {
connectListener.onConnect(bind);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "ServiceConnection onServiceDisconnected start reconnect");
//断开连接,分发bind情况
bind = false;
if (connectListener != null) {
connectListener.onConnect(bind);
}
}
};
/**
* 创建binder的回调接口,一个app只能有一个,这里服务默认创建一个,避免多创建
*/
private final com.kx.aidl.CarPropertyCallBack carPropertyCallBackLocation = new com.kx.aidl.CarPropertyCallBack.Stub() {
@Override
public void onCarPropertyCallBack(CarProperty carProperty) throws RemoteException {
//将数据分发给客户端
if (carServiceManager != null) {
if (carPropertyCallBack != null) {
carPropertyCallBack.onCarPropertyCallBack(carProperty);
}
} else {
Log.d(TAG, "setCarProperty manager isEmpty");
}
}
};
/**
* 初始化重连
*/
private void initReconnect() {
//清空连接情况
closeReconnect();
//创建子线程
handlerThread = new HandlerThread("CarServiceManager");
handlerThread.start();
reconnectHandler = new Handler(handlerThread.getLooper());
//开始重连
startReconnect();
}
/**
* 重连机制,开始定时重连,超过重连 RECONNECT_TIME 次数将不再重连
*/
private void startReconnect() {
if (reconnectHandler != null) {
//判断是否超过重连
if (mConnectionRetryCount >= RECONNECT_TIME) {
Log.d(TAG, "服务端异常 reconnect timed out ");
//重连超时,清空重连数据
closeReconnect();
return;
}
mConnectionRetryCount++;
Log.d(TAG, "服务端异常,重连 " + mConnectionRetryCount);
stopReconnect();
//开始绑定服务
bindService();
reconnectHandler.postDelayed(reconnectRunnable, RECONNECT_HEARTBEAT);
}
}
/**
* 移除handler的callback
*/
private void stopReconnect() {
if (reconnectHandler != null) {
reconnectHandler.removeCallbacks(reconnectRunnable);
}
}
/**
* 清空重连数据类型
*/
private void closeReconnect() {
mConnectionRetryCount = 0;
if (handlerThread != null) {
if (reconnectHandler != null) {
reconnectHandler.removeCallbacks(reconnectRunnable);
reconnectHandler = null;
}
handlerThread.quit();
handlerThread = null;
}
}
/**
* 绑定服务
*/
private void bindService() {
if (context != null) {
Intent intent = new Intent(CLASS_NAME);
intent.setPackage(PACKAGE_NAME);
boolean bind = context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
Log.d(TAG, "bindService binder " + bind);
} else {
Log.d(TAG, "bindService context isEmpty ");
}
}
public static CarServiceManager getInstance() {
if (instance == null) {
synchronized (CarServiceManager.class) {
if (instance == null) {
instance = new CarServiceManager();
}
}
}
return instance;
}
public void init(Context context, int[] feedbackSignals) {
this.context = context;
this.feedbackSignals = feedbackSignals;
bindService();
}
/**
* 设置数据回调接口,数据从这个接口分发出去
*/
public interface CarPropertyCallBack {
void onCarPropertyCallBack(CarProperty carProperty);
}
public void setCarPropertyCallBack(CarPropertyCallBack carPropertyCallBack) {
this.carPropertyCallBack = carPropertyCallBack;
}
public interface ConnectListener {
void onConnect(Boolean connect);
}
/**
* 设置连接成功回调接口
*/
public void setOnConnectListener(ConnectListener connectListener) {
//如果当前状态是连接成功的,直接返回连接状态
if (bind) {
this.connectListener.onConnect(true);
}
this.connectListener = connectListener;
}
public void setCarProperty(int property, int value) {
if (carServiceManager != null) {
try {
carServiceManager.setCarProperty(property, value);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
Log.d(TAG, "setCarProperty manager isEmpty");
}
}
public int getCarProperty(int property) {
if (carServiceManager != null) {
try {
return carServiceManager.getCarProperty(property);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
Log.d(TAG, "setCarProperty manager isEmpty");
}
return -10000;
}
public void inOutCarProperty(CarProperty property) {
if (carServiceManager != null) {
try {
carServiceManager.inOutCarProperty(property);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
Log.d(TAG, "inOutCarProperty manager isEmpty");
}
}
public void outCarProperty(CarProperty property) {
if (carServiceManager != null) {
try {
carServiceManager.outCarProperty(property);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
Log.d(TAG, "outCarProperty manager isEmpty");
}
}
public void inCarProperty(CarProperty property) {
if (carServiceManager != null) {
try {
carServiceManager.inCarProperty(property);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
Log.d(TAG, "outCarProperty manager isEmpty");
}
}
}
- 打包成jar包
jar -cvf myAidl.jar * 打包所有问题件

![]()
jar -cvf myAidl.jar *
- 客户端导入jar包
build.gradle.kts
dependencies {
implementation(files("libs/myAidl.jar"))
}
客户端端注册 AndroidManifest.xml 必要属性
<queries>
<package android:name="com.kx.client" />
<intent>
<action android:name="com.kx.client.CarService" />
</intent>
</queries>
客户端代码注册和调用
CarServiceManager.getInstance().init(AidlActivity.this,new int[]{});
CarServiceManager.getInstance().setOnConnectListener(new CarServiceManager.ConnectListener() {
@Override
public void onConnect(Boolean connect) {
if (connect) {
CarServiceManager.getInstance().setCarPropertyCallBack(new CarServiceManager.CarPropertyCallBack() {
@Override
public void onCarPropertyCallBack(CarProperty carProperty) {
Log.d(TAG, "onCarPropertyCallBack property " + carProperty
+ " value " + carProperty.value+" currentThread "+Thread.currentThread());
}
});
}
}
});

2538

被折叠的 条评论
为什么被折叠?



