一文搞懂Android AIDL

一文搞懂Android AIDLAIDL AndroidInter 用于在 Android 应用中实现进程间通信 IPC

大家好,欢迎来到IT知识分享网。

介绍

AIDL(Android Interface Definition Language)用于在Android应用中实现进程间通信(IPC)。它允许不同应用或服务间的数据传递和方法调用,确保不同进程间能够相互访问和操作。通过AIDL,开发者可以定义一个接口,然后在服务端和客户端实现这个接口,实现跨进程的交互。背景上,AIDL主要解决了Android系统中的进程隔离问题,使得不同应用或进程能够安全有效地共享数据和功能。

示例

话不多说,直接开搂!

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

step1

 buildFeatures { aidl true } 

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

step2

此时的 libary 是作为主项目的子模块,当然 你也可以直接写在主模块中。

写之前先了解下在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 类可以用于在进程间传递一组键值对的集合,类似于一个映射表。
  1. List 和 Map
  • List<T>:支持基本数据类型和支持 Parcelable 接口的对象类型的列表。
  • Map<K, V>:支持基本数据类型和支持 Parcelable 接口的对象类型的映射表。
  1. Parcelable
  • 自定义的类如果实现了 Parcelable 接口,也可以在 AIDL 中使用。这是一个用来序列化对象的接口,可以将对象数据从一个进程传递到另一个进程。
  1. IBinder
  • IBinder 接口可以在 AIDL 中作为参数传递,允许在不同的进程间传递服务对象的引用。

step3

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

创建服务接口(com.xaye.aidl_1):

可以参照上图

// IRemoteService.aidl package com.xaye.library; // 引用 VideoParams 和 VideoCallback import com.xaye.library.VideoParams; import com.xaye.library.VideoCallback; interface IRemoteService { 
    void processVideoClip(in VideoParams params, in VideoCallback callback); } 
VideoParams

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

// VideoParams.aidl package com.xaye.library; import com.xaye.library.VideoParams; parcelable VideoParams; 
VideoCallback

一个简单的回调接口。

// VideoCallback.aidl package com.xaye.library; interface VideoCallback { 
    void onSuccess(String filePath); void onError(String error, String throwableMessage); } 

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

step4

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

public class VideoService extends Service { 
    @Nullable @Override public IBinder onBind(Intent intent) { 
    return new IRemoteService.Stub() { 
    @Override public void processVideoClip(VideoParams params, VideoCallback callback) { 
    try { 
    callback.onSuccess("aidl 1 回调数据!"); } catch (RemoteException e) { 
    e.printStackTrace(); } } }; } } 

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

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

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

至此,服务端代码完成。

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

step5 :实现客户端代码(com.xaye.aidl_2)

服务端代码如下👇

class TestActivity : AppCompatActivity() { 
    private val TAG = "TestActivity" private lateinit var binding: ActivityTestBinding private var remoteService: IRemoteService? = null private var connection = object : ServiceConnection { 
    override fun onServiceConnected(name: ComponentName?, service: IBinder?) { 
    Log.i(TAG,"test aidl client onServiceConnected") remoteService = IRemoteService.Stub.asInterface(service) } override fun onServiceDisconnected(name: ComponentName?) { 
    Log.i(TAG,"test aidl client onServiceDisconnected") } } override fun onCreate(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(){ 
    override fun onSuccess(filePath: String?) { 
    Log.i(TAG,"test aidl client onSuccess $filePath") runOnUiThread { 
    Toast.makeText(this@TestActivity,filePath,Toast.LENGTH_LONG).show() } } override fun onError(error: String?, throwableMessage: String?) { 
    Log.i(TAG,"test aidl client onError $error") runOnUiThread { 
    Toast.makeText(this@TestActivity,"$error $throwableMessage",Toast.LENGTH_LONG).show() } } }) } } private fun bindService() { 
    val intent = Intent() intent.action = "com.xaye.libary.IRemoteService"//子模块中注册时 要求的action intent.setPackage("com.xaye.aidl_1") //目标应用包名,注意不是子模块的 val bound = 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 是服务端所属的应用包名,即使你的服务在子模块中,也要写主应用包名!

至此,全剧终。


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

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

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/117529.html

(0)
上一篇 2025-11-20 12:20
下一篇 2025-11-20 12:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信