AIDL关键点

AIDL(Android Interface Definition Language),实际使用其实也是绑定一个Service。

1. 一个.aidl接口定义示例

2. 建立连接:

final Intent serviceIntent = ApiAvailability.getInstance().getAvailableServicesInstance(context);
isServiceConnecting.set(context.bindService(serviceIntent, o3drServicesConnection, Context.BIND_AUTO_CREATE));

关键是bindService的前两个参数

3. 第二个参数ServiceConnection

private final ServiceConnection o3drServicesConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // 绑定服务成功
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        // 绑定服务失败
    }

};

4. 绑定服务成功内的操作,需要的几个关键方法

Stub.asInterface(IBinder) // 获取AIDL接口对象
asBinder() // 获取binder对象
asBinder().linkToDeath() // 注册断开监听
asBinder().unlinkToDeath() // 取消断开监听
asBinder().pingBinder() // 判断是否还连接

4.1 获取 IDroidPlannerServices这个AIDL接口对象

// 最后的参数就是 onServiceConnected() 回调中的IBinder对象
IDroidPlannerServices o3drServices = IDroidPlannerServices.Stub.asInterface(service);

4.2 利用接口对象注册Binder断掉的监听

// binderDeathRecipient 是监听对象
o3drServices.asBinder().linkToDeath(binderDeathRecipient, 0);

4.3 判断是否还连接

o3drServices.asBinder().pingBinder();

4.4 取消Binder断掉的监听,一般在unbindService时

o3drServices.asBinder().unlinkToDeath(binderDeathRecipient, 0);
context.unbindService(o3drServicesConnection);

4.5 AIDL接口对象中定义的方法使用

例如上面图片中的 getServiceVersionCode() 等方法。

5. 第一个参数Intent

Intent getAvailableServicesInstance(@NonNull final Context context) {
    final PackageManager pm = context.getPackageManager();

    //Check if an instance of the services library is up and running.
    final Intent serviceIntent = new Intent(SERVICES_CLAZZ_NAME);
    final List<ResolveInfo> serviceInfos = pm.queryIntentServices(serviceIntent, PackageManager.GET_META_DATA);
    if(serviceInfos != null && !serviceInfos.isEmpty()){
        for(ResolveInfo serviceInfo : serviceInfos) {
            final Bundle metaData = serviceInfo.serviceInfo.metaData;
            if (metaData == null)
                continue;

            final int coreLibVersion = metaData.getInt(METADATA_KEY, INVALID_LIB_VERSION);
            // 服务已经被其它进程启动并且版本高于设定版本,使用此服务
            if (coreLibVersion != INVALID_LIB_VERSION && coreLibVersion >= VersionUtils.getCoreLibVersion(context)) {
                serviceIntent.setClassName(serviceInfo.serviceInfo.packageName, serviceInfo.serviceInfo.name);
                return serviceIntent;
            }
        }
    }

    //Didn't find any that's up and running. Enable the local one
    DroidPlannerService.enableDroidPlannerService(context, true);
    serviceIntent.setClass(context, DroidPlannerService.class);
    return serviceIntent;
}

首次启动这个服务时,enableDroidPlannerService() 很关键,具体如下:

public static void enableDroidPlannerService(Context context, boolean enable){
    final ComponentName serviceComp = new ComponentName(context, DroidPlannerService.class);
    final int newState = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
            : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
    context.getPackageManager().setComponentEnabledSetting(serviceComp, newState, PackageManager.DONT_KILL_APP);
}

最后还有在Manifest.xml中对 DroidPlannerService 的注册:

<service
    android:name="org.droidplanner.services.android.impl.api.DroidPlannerService"
    android:enabled="false">

    <!-- Filter and meta data for the Tower lib runtime -->
    <!-- 有intent-filter所以android:exported属性默认为true -->
    <intent-filter>
        <action android:name="com.o3dr.services.android.lib.model.IDroidPlannerServices" />
    </intent-filter>

    <meta-data
        android:name="com.o3dr.dronekit.android.core.version"
        <!-- 版本号的配置 -->
        android:value="30200" />
</service>

你可能感兴趣的:(dronekit,android)