android 全网最全的AIDL

  • 环境搭建

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());

                        }
                    });
                }
            }
        });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值