Android AIDL示例及高版本问题

AIDL使用示例及高版本问题

关于Android AIDL不论是官方文档,还是网络上的资料信息,都讲解的很完整,包括Binder机制。

这里只是将AIDL 跨进程调用进行一次使用的记录。

服务端app

1

在作为服务端的app,需要定义一个AIDL文件,即扩展名.aidl的接口文件,在文件内定义接口方法。

AIDL概览:传送门


interface ILogCollector {

    /**
     * Decimal: 65280
     */
    const int TRANSACT_CODE_BASTIC_TYPES = 0xFF00;

    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString) = 65280;
}

使用Android Studio 环境进行编译,会生成一个同名的Java接口文件ILogCollector.java

AIDL文件爱你定义
AIDL编译生成Java类

2

创建Service类,并在Service内实现AIDL接口编译生成的Stub类。

public class LogCollectorService extends Service {

    private static final String TAG = LogCollectorService.class.getSimpleName();

    /**
     * LogCollector服务端实现。
     */
    private final ILogCollector.Stub mCollectorBinder = new ILogCollector.Stub() {

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString)
                throws RemoteException {

            Log.d(TAG, "服务端 basicTypes() 方法被调用");
        }
    };

    @NonNull
    @Override
    public IBinder onBind(Intent intent) {

        Log.i(TAG, "返回服务端Binder");
        return mCollectorBinder;
    }
}

3

在Manifest内注册Service,且可以定义一个对应的权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools">
  <!-- 声明一个collect log权限 -->
  <permission android:name="com.sanren1024.permission.COLLECT_LOG" />
  <application
    // ...
    tools:targetApi="31">
    <service
      android:name=".LogCollectorService"
      android:enabled="true"
      android:exported="true"
      android:permission="com.sanren1024.permission.COLLECT_LOG">
      <intent-filter>
        <action android:name="com.sanren1024.logcollector.LOG_SERVICE" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
    </service>
  </application>
</manifest>

这样服务端最简单的app定义好了。

客户端app

创建一个新的app工程,用以测试app服务端。

AIDL客户端定义及调用传送门

在客户端实现中定义ServiceConnection,进行bindService()调用。

// MainActivity.java关键代码
    private ILogCollector mRemoteProxy;

    private final ServiceConnection mServConn = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

            mRemoteProxy = ILogCollector.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

            mRemoteProxy = null;
        }
    };

    // bindService()绑定远程服务
    if (v.getId() == R.id.button_bind) {
        Intent servIntent = new Intent("com.sanren1024.logcollector.LOG_SERVICE");
        servIntent.setClassName("com.sanren1024.logcollector", "com.sanren1024.logcollector.LogCollectorService");
        //            servIntent.setAction("com.sanren1024.logcollector.LOG_SERVICE");
        servIntent.setPackage("com.sanren1024.logcollector");
        boolean launchResult = bindService(servIntent, mServConn, Context.BIND_AUTO_CREATE);
        Toast.makeText(this, "启动结果:" + launchResult, Toast.LENGTH_SHORT).show();
        return;
    }

    // 方法调用
    if (v.getId() == R.id.button_invoke && mRemoteProxy != null) {
        try {
            mRemoteProxy.basicTypes(1, 2, false, 3.0f, 4.5d, "nicholas");
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
        return;
    }

	// 解绑
    if (v.getId() == R.id.button_unbind && mRemoteProxy != null) {

        unbindService(mServConn);
    }

这样在运行时,客户端app即可以调用到服务端app。

高版本问题

上述的AIDL定义,程序实现,调用均在Android 8上执行,可以成功调用。

但在Android 12上测试存在服务端app无法被调用起的问题。

工程的 targetSDK 33的值是33,读了文章CSDN AIDL报错,bindService一直连接不上、不起作用,并查看官方文档Android 11 中的软件包可见性可以知道原因。

在Android 11(API Level 30)以上,App可查询的应用列表被看作是私有敏感数据,即要查询或调用其他app时,会受到系统限制,也就是Android上对应用的访问查询做了更加严格的限制。

按照blog解释,基于对私有数据越来越严格的控制,且在一般场景下,app不需要完全查询调用一个设备上的其他所有的应用。因此Android 11上引入了app查询或与其他应用交互的新特性:在manifest中引入新标签<queryies>,显式声明App需要查询/交互的其他应用。

可以查看官方的<queryies>使用说明,解决在高版本Android上无法IPC调用的问题。

HarmonyOS上运行

目前,android app还是可以在HarmonyOS系统上运行,因此也在Huawei设备上运行,但没有成功,似乎是HMS框架的一个内部错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VoidHope

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值