发布时间:2025-06-24 20:19:53  作者:北方职教升学中心  阅读量:652


通过AIDL,开发者可以定义一个接口,然后在服务端和客户端实现这个接口,实现跨进程的交互。

示例

话不多说,直接开搂!

下面示例创建了两个安卓项目,一个服务端(com.xaye.aidl_1)一个客户端(com.xaye.aidl_2)

step1

如果你的项目中没有使用过AIDL,那么当你创建AIDL文件时,会遇到下图这种情况👇
在这里插入图片描述
解决方法是在你的build.gradle文件中添加以下代码

buildFeatures {        aidl true    }

然后再rebuild一下就可以啦(●’◡’●)

step2

需要创建一个AIDL服务的接口,因为要供其他应用调用,创建AIDL文件时,需要右击main文件夹创建,因为AIDL需要和java文件夹在同级目录下,效果如下👇
在这里插入图片描述
写之前先了解下在AIDL(Android Interface Definition Language)中,默认支持的几种数据类型:

  1. 基本数据类型
  • boolean:布尔值(true 或 false)
  • byte:8 位有符号整数
  • char:16 位 Unicode 字符
  • double:64 位双精度浮点数
  • float:32 位单精度浮点数
  • int:32 位有符号整数
  • long:64 位有符号整数
  • short:16 位有符号整数
  1. Java 对象
  • String:字符串
  • CharSequence:字符序列
  1. Bundle
  • Bundle类可以用于在进程间传递一组键值对的集合,类似于一个映射表。

    // VideoParams.aidlpackagecom.xaye.library;importcom.xaye.library.VideoParams;parcelable VideoParams;
    VideoCallback

    一个简单的回调接口。

  1. IBinder
  • IBinder接口可以在 AIDL 中作为参数传递,允许在不同的进程间传递服务对象的引用。

    // VideoCallback.aidlpackagecom.xaye.library;interfaceVideoCallback{voidonSuccess(String filePath);voidonError(String error,String throwableMessage);}

    aidl包下要写的东西就这么些,其他应用要使用的话,需要把整个aidl文件夹复制到main下。


    AIDL没什么难的,只是平时用的比较少,记得刚入行的时候听到感觉好高级,因为工作中没有需求,就一直没有机会去了解(其实就是懒😄),当亲手实操下,看到数据返回时,内心还是有点兴奋的,又get到一个技能,哈哈。

step3

为了上点难度,咱们自定义两种类型 VideoParamsVideoCallback

创建服务接口:
// IRemoteService.aidlpackagecom.xaye.library;// 引用 VideoParams 和 VideoCallbackimportcom.xaye.library.VideoParams;importcom.xaye.library.VideoCallback;interfaceIRemoteService{voidprocessVideoClip(inVideoParams params,inVideoCallback callback);}
VideoParams

VideoParams 是一个java bean,代码中需要对其序列化,在aidl中使用就是下面这样。

  1. List 和 Map
  • List<T>:支持基本数据类型和支持 Parcelable 接口的对象类型的列表。

    介绍

    AIDL(Android Interface Definition Language)用于在Android应用中实现进程间通信(IPC)。这是一个用来序列化对象的接口,可以将对象数据从一个进程传递到另一个进程。

    至此… 呃,还有一点,在清单文件中注册该服务,这里主要注意要指定 action,因为其他应用需要该 action去找到你的服务。

    publicclassVideoService extends Service {@Nullable@OverridepublicIBinder onBind(Intent intent){returnnew IRemoteService.Stub(){@Overridepublicvoid processVideoClip(VideoParams params,VideoCallback callback){try{callback.onSuccess("aidl 1 回调数据!");}catch(RemoteException e){e.printStackTrace();}}};}}

    这个 IRemoteService需要rebuild 后才会有,没build会爆红。

  1. Parcelable
  • 自定义的类如果实现了 Parcelable 接口,也可以在 AIDL 中使用。

    补充:在实际开发中其实没必要传实体类,定义和接收都比较繁琐,直接将实体类使用fastjson 转为json字符串,客户端接收的时候再解析下json就行了!

    step5 :实现客户端代码

    无图言吊,上图,客户端代码结构
    在这里插入图片描述
    正如上面说的,把aidl文件夹 直接复制进来,然后,客户端调用 processVideoClip方法,需要VideoParamsVideoCallback两个类,因为 VideoCallback类中的数据aidl默认都支持,所以你rebuild后就能直接导入,而VideoParams是自定义数据类,需要把它放到java包 和 服务端同包名下即可,这样在运行时就能通过包名找到同一个VideoParams了。

    源码已上传csdn资源,0积分:AIDL客户端服务端源码

  • Map<K, V>:支持基本数据类型和支持 Parcelable 接口的对象类型的映射表。背景上,AIDL主要解决了Android系统中的进程隔离问题,使得不同应用或进程能够安全有效地共享数据和功能。它允许不同应用或服务间的数据传递和方法调用,确保不同进程间能够相互访问和操作。

    <serviceandroid:name=".VideoService"android:exported="true"><intent-filter><!--需要接受的action,其他应用指定--><actionandroid:name="com.xaye.libary.IRemoteService"/></intent-filter></service>

    至此,服务端代码完成。

    step4

    如 step2 图示,在java包中 VideoParams 就是一个实现序列化后的bean,VideoService 是一个普通的安卓Service,在这个服务里处理其他应用发送的事件,代码如下,就简单处理返回了下。

    服务端代码如下👇

    classTestActivity :AppCompatActivity(){privatevalTAG ="TestActivity"privatelateinitvarbinding:ActivityTestBinding    privatevarremoteService:IRemoteService?=nullprivatevarconnection =object:ServiceConnection {overridefunonServiceConnected(name:ComponentName?,service:IBinder?){Log.i(TAG,"test aidl client onServiceConnected")remoteService =IRemoteService.Stub.asInterface(service)}overridefunonServiceDisconnected(name:ComponentName?){Log.i(TAG,"test aidl client onServiceDisconnected")}}overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)binding =ActivityTestBinding.inflate(layoutInflater)setContentView(binding.root)bindService()binding.btnTest.setOnClickListener{Log.i(TAG,"test aidl client click  remoteService == null : ${remoteService ==null}")remoteService?.processVideoClip(VideoParams("","",""),object:VideoCallback.Stub(){overridefunonSuccess(filePath:String?){Log.i(TAG,"test aidl client onSuccess $filePath")runOnUiThread {Toast.makeText(this@TestActivity,filePath,Toast.LENGTH_LONG).show()}}overridefunonError(error:String?,throwableMessage:String?){Log.i(TAG,"test aidl client onError $error")runOnUiThread {Toast.makeText(this@TestActivity,"$error$throwableMessage",Toast.LENGTH_LONG).show()}}})}}privatefunbindService(){valintent =Intent()intent.action ="com.xaye.libary.IRemoteService"//子模块中注册时 要求的actionintent.setPackage("com.xaye.aidl_1")//目标应用包名,注意不是子模块的valbound =bindService(intent,connection,BIND_AUTO_CREATE)if(bound){Log.i(TAG,"test aidl client bindService succeed")}else{Log.i(TAG,"test aidl client bindService failed")}}}

    首先就是bindService去绑定远程服务,在ServiceConnection中拿到服务端的服务,然后就可以愉快滴调用服务端方法了,这里主要注意下 intent.action是服务注册时指定的!setPackage是服务端所属的应用包名,即使你的服务在子模块中,也要写主应用包名!

    安装上客户端 和 服务端应用,运行上面代码,效果如下图
    在这里插入图片描述

    至此,全剧终。