前语

考虑到后边有需求到车载或者其他多程序交互的场景,因而我最近也接触了下AIDL这个东西,AIDL在写文本时也是第一次运用,所以咱们首要重视完成AIDL要具有什么东西。

需求注意的是,本文可能存在一些错误解释,期望读者阅读时注意甄别,实践出真知,对内容有爱好的话就快试试看!

什么是AIDL

Android Interface Definition Language(Android接口界说语言),利用AIDL咱们能够生成一套IPC通讯代码,也便是进程间通讯,咱们知道一个APP默认状况下是一个进程,因而微观上说AIDL能够用于不同APP之间的通讯。

AIDL是一种模板语法,类似Java的接口,界说后生成的代码便是Java的接口类,内部有完成了IPC通讯,可是由于这些代码是重复的,所以安卓交心的给咱们一个模型生成这些代码。

AIDL生成的接口中存在一个Binder的示例,APP能够通过Service来运用它,其他APP绑定这个Service就能够彼此通讯了。

试验条件

咱们模拟2个APP

  • 服务端APP
  • 客户端APP
  • AIDL模块(供其他模块或者APP引进运用)

实操

咱们仅仅要完成这个跨进程通讯,因而功能不太重要,咱们下面运用各自办法目的仅仅为了传递数据给通讯双方。

完成AIDL模块

咱们先创立一个Android项目,这个项目就作为客户端APP了(为了便利)。

AIDL 跨进程通讯学习试验 API34

接下来咱们创立一个模块,对应图上便是aidl-sdk,咱们需求在里面去编写AIDL的模板和Bean类。

启用AIDL

AIDL 跨进程通讯学习试验 API34

在正式开始前咱们得在gradle文件里编写下面的装备,不然待会咱们没办法创立AIDL文件。

buildFeatures { aidl = true }

创立AIDL文件

AIDL 跨进程通讯学习试验 API34

让咱们挑选AIDL-SDK模块,点击新建,找到AIDL,假如你没有装备上面说的选项,那么这儿是没办法勾选的哦。

下面我起个姓名叫做IMyAidlInterface,你会发现多了一个aidl的文件夹,其间就有IMyAidlInterface.adil文件。

咱们在里面这么写,就完成传递两个数字返回相加成果,怎么说?看上去如同和Java语法很像对不对?不过我发现这儿没有提词,有点不太习惯。

// IMyAidlInterface.aidl
package com.imcys.aidl_sdk;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
  int add(int a, int b);
}

AIDL 跨进程通讯学习试验 API34

接下来,咱们点击Build,不Build这个AIDL文件不会变成接口类。

AIDL 跨进程通讯学习试验 API34

当咱们再次查看时会发现现已生成了对应的Java文件。

AIDL 跨进程通讯学习试验 API34

这个接口文件里有一个抽象类,这个Stub的结构办法就会给咱们一个Binder,后边咱们就能够在服务中运用它。

完成服务端APP

咱们回到最外层,创立一个新的APP项目模块。

AIDL 跨进程通讯学习试验 API34

这么做是为了咱们待会便利引进写好的AIDL模块,就创立在一个大项目下面了。

不要忘掉给这个新建的服务端APP模块引进前面创立的aidl-sdk,不然生成的接口这个模块看不到。

implementation(project(":aidl-sdk"))

还记得吗?我前面说这个AIDL生成的接口中有个Binder,这东西要给服务来用,所以咱们直接创立一个项目奥。

下面我创立一个AIDLDemoServer类作为Service

AIDL 跨进程通讯学习试验 API34

而onBind办法正好需求一个Binder,那么咱们就直接给他传递生成的Binder,让它来接管服务的通讯。

AIDL 跨进程通讯学习试验 API34

这儿咱们继承生成接口的Stub类,完成它里面的办法,这些办法实际上便是咱们刚刚在模板界说的,注意,下面的三个办法是我后来写在模板的,因而咱们暂时不用重视。

咱们给add进行了完成,它的功能便是相加就能够了,然后咱们把Binder传递给onBind就好。

服务注册

千万别忘掉注册咱们的服务:

    <service
            android:name=".AIDLDemoServer"
            android:enabled="true"
            android:exported="true"
            tools:ignore="ForegroundServicePermission">
            <intent-filter>
                <action android:name="com.imcys.aidldemo.AIDLSERVICE"/>
            </intent-filter>
        </service>

注意咱们这儿加了一个action,用于绑定时过滤。

免杀扩展

让咱们的服务成为前台服务,降低体系杀掉的状况,这个安卓13有一些权限调整,需求你指定前台服务的类型。

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>

服务概览 | Background work | Android Developers (google.cn)

详细看上面地址,我这儿就不做这一步了。

完成客户端APP

同样的,咱们给APP引进前面创立的aidl-sdk,不然生成的接口这个模块看不到。

implementation(project(":aidl-sdk"))

绑定服务

AIDL 跨进程通讯学习试验 API34

绑定服务的办法类似咱们正常在APP内绑定服务,可是由于不在一个APP咱们需求指定包名和这个服务的详细类。


    private fun bindAIDLServer() {
        val intent = Intent()
        intent.setAction("com.imcys.aidldemo.AIDLSERVICE")
        intent.setComponent(
            ComponentName(
                "com.imcys.aidldemo.server",
                "com.imcys.aidldemo.server.AIDLDemoServer"
            )
        )
        val suc = bindService(intent, serviceConnection, BIND_AUTO_CREATE)
        Log.i(TAG, "bindToService: $suc")
    }

注意咱们这儿用了setAction,是由于服务端APP注册服务时指定了action。

这块需求传一个ServiceConnection,咱们看看如何获取它。

AIDL 跨进程通讯学习试验 API34

咱们看到它也返回了IBinder,很巧的是,生成的IMyAidlInterface中有一个转化的办法。

iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service)

非常巧妙,咱们获取到了iMyAidlInterface,现在咱们调用iMyAidlInterface的办法就会和服务端APP进行通讯了。

让咱们运转看看,注意不要在onServiceConnected执行iMyAidlInterface,由于那是主线程,我这块仅仅为了演示。

运转成果

AIDL 跨进程通讯学习试验 API34

能够看到,咱们成功了,返回成果是30,它将10和20加在了一同,这样咱们就完成了跨进程通讯。

传递Bean

这是拓展内容,有爱好的能够看看。

创立Bean

AIDL 跨进程通讯学习试验 API34

咱们在aidl-sdk模块创立bean包,在里面创立一个AIDLMessage,由于AIDL不能直接传输它,因而咱们需求序列化,这儿谷歌推荐的是Parcelable,这个完成咱们能够在网上找一下。

创立AIDL

AIDL 跨进程通讯学习试验 API34

咱们需求界说一个新的AIDL

parcelable AIDLMessage;

AIDL 跨进程通讯学习试验 API34

可是不要忘掉,咱们得在之前的AIDL中界说一个办法来运用它,现在假设它是返回类型。

注意,咱们得导入它的包,和正常导包的写法是相同的。

服务端完成

AIDL 跨进程通讯学习试验 API34

Service的完成是简略的,咱们相当于new一个AIDLMessage出去。

客户端完成

AIDL 跨进程通讯学习试验 API34

Log.i(TAG, "特别序列化${iMyAidlInterface.buildAIDLMessage(1, "补白").msg}")

咱们在客户端调用一下,看看运转成果。

AIDL 跨进程通讯学习试验 API34

毫无疑问,成功了。

文末

本文内容可能并不完全正确,期望帮助到了咱们,有问题能够在谈论区告诉我,另外最近在投年度创作者榜单,期望咱们能够投我一票。