参考资料:https://blog.csdn.net/geyichongchujianghu/article/details/130045373
这个连接是Java的代码,我根据它的链接写了一个kotlin版本的。
AIDL(Android Interface Definition Language)是Android平台上用于进程间通信(IPC)的一种接口定义语言。它允许不同进程中的组件(如服务和服务、服务和活动等)相互通信。
AIDL的主要特点包括:
- 跨进程通信:AIDL允许不同进程中的组件相互通信,这使得应用可以更好地利用设备的多核处理器,提高性能和响应速度。
- 接口定义:通过AIDL,开发者可以定义一个接口,并在这个接口中声明需要跨进程传递的方法和数据类型。
- 自动生成代码:Android SDK提供了一个编译器,它可以根据AIDL接口定义自动生成Java代码,这些代码负责处理跨进程通信的细节。
- 支持多种数据类型:AIDL支持基本数据类型、字符串、列表、映射等多种数据类型,以及自定义的Parcelable对象。
- 安全性:AIDL通信是通过Binder机制实现的,Binder机制提供了进程间通信的安全性,确保只有授权的进程可以访问服务。
使用AIDL的步骤通常包括:
- 定义AIDL接口(.aidl文件)。
- 实现AIDL接口的服务端。
- 在客户端使用AIDL接口与服务端通信。
AIDL是Android平台上实现跨进程通信的重要工具,它为开发者提供了一种方便、高效的方式来实现不同进程间的数据交换和方法调用。
下面介绍了AIDL的使用例子,创建了两个App,一个是服务端的mainapp,一个是客户端的otherapp,它们会被创建在一个工程里,这样也会方便调试。
一、创建两个App
新建一个mainapp,我新建了一个aidlTest,创建了一个mainapp,这个aidlTest文件夹并没有什么用。
把MainActivity重命名成MainAppActivity
再添加一个otherapp的module
模块名字为otherapp
二、在mainapp里创建一个service
先在mainapp中实现一个service,MainAppActivity类中创建了service
service名字为MainAppService
修改MainAppAcitvity里的代码
class MainAppActivity : AppCompatActivity() {private val TAG = "AIDL-MainAppActivity"override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()setContentView(R.layout.activity_main)ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)insets}Log.v(TAG, "onCreate()")}override fun onDestroy() {super.onDestroy()Log.v(TAG, "onDestroy()")}
}
MainAppService里的改动,我们又重写了onCreate()、onStartCommand()和onDestroy()这3个方
法,它们是每个Service中最常用到的3个方法了。其中:
- onCreate()方法会在Service创建的时候调用
- onStartCommand()方法会在每次Service启动的时候调用,
- onDestroy()方法会在Service销毁的时候调用。
- onBind是被客户端绑定时执行
- onUnbind(Intent intent):被客户端解绑时执行
class MainAppService : Service() {private val TAG = "AIDL-MainAppService"override fun onCreate() {super.onCreate()}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {return super.onStartCommand(intent, flags, startId)}override fun onBind(intent: Intent): IBinder {TODO("Return the communication channel to the service.")}override fun onUnbind(intent: Intent?): Boolean {Log.v(TAG, "onUnbind()")return super.onUnbind(intent)}override fun onDestroy() {super.onDestroy()Log.v(TAG, "onDestroy()")}
}
三、mainapp里实现AIDL
在创建aidl前,需要在mainapp的gradle里,配置打开aidl
buildFeatures {aidl = true
}
在mainapp的main目录下创建一个名为IAppAidlInterface.aidl的文件
在IAppAidlInterface里添加setStringData这个AIDL接口定义了一个名为IAppAidlInterface
的接口,它包含了两个方法:basicTypes
和setStringData
。
basicTypes
方法展示了在AIDL接口中可以使用的一些基本数据类型作为参数。这些基本数据类型包括整型(int
)、长整型(long
)、布尔型(boolean
)、浮点型(float
)、双精度浮点型(double
)和字符串型(String
)。这个方法没有返回值,它的目的是演示如何在AIDL接口中使用这些基本数据类型。setStringData
方法接受一个字符串参数(String strData
),并将其设置为某个值。这个方法也没有返回值,它的目的是演示如何在AIDL接口中传递字符串数据。
这个AIDL接口定义了两个没有返回值的方法,它们可以用于跨进程通信。在实际应用中,你可以根据需要定义更多的方法和参数,以实现不同进程间的数据交换和方法调用。
interface IAppAidlInterface {/*** 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);void setStringData(String strData);
}
在AIDL创建完成后,点击重新编译后就有生成的java类了。在Android中,当你定义了一个AIDL(Android Interface Definition Language)接口后,Android的编译器会自动为你生成一个Java接口类。这个生成的接口类继承自android.os.IInterface,并包含了你在AIDL文件中定义的方法。
四.otherapp中也实现AIDL
把mainapp里的aidl文件复制到otherapp里,并开启aidl后,就也能看到生成的aidl java文件
五、在mainapp中添加代码
现在MainAppService中实例化Binder
package com.example.mainappimport android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Logclass MainAppService : Service() {private val TAG = "AIDL-MainAppService"private val mStub = AppAidlInterfaceStub()/* * 实现IAppAidlInterface.Stub抽象类,* 用于实现IAppAidlInterface.aidl中的接口函数* onBinder()时返回匿名内部类实例*/inner class AppAidlInterfaceStub : IAppAidlInterface.Stub() {var mStrData = ""var mSetServiceRunning = trueoverride fun basicTypes(anInt: Int,aLong: Long,aBoolean: Boolean,aFloat: Float,aDouble: Double,aString: String?) {}override fun setStringData(strData: String?) {mStrData = strData.toString()}}override fun onCreate() {Log.v(TAG, "onCreate()")super.onCreate()}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {Log.v(TAG, "onStartCommand()")return super.onStartCommand(intent, flags, startId)}//在onBinder()中启动一个线程,每1秒轮询接收客户端发送过来的数据override fun onBind(intent: Intent): IBinder {mStub.mSetServiceRunning = trueThread {while(mStub.mSetServiceRunning) {try {Thread.sleep(1000);Log.v(TAG, "mStrData:${mStub.mStrData}")} catch (e: InterruptedException) {e.printStackTrace()}}}.start()return mStub //返回AppAidlInterfaceStub实例}//在unBind里清除运行标志,让线程能够退出override fun onUnbind(intent: Intent?): Boolean {Log.v(TAG, "onUnbind()")mStub.mSetServiceRunning = falsereturn super.onUnbind(intent)}override fun onDestroy() {super.onDestroy()Log.v(TAG, "onDestroy()")}
}
需要确保mainappservice在AndroidMainfiest.xml里添加了Service标签
<applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Mainapp"tools:targetApi="31"><serviceandroid:name=".MainAppService"android:enabled="true"android:exported="true"></service><!-- .... -->
</application>
六、OtherApp里OtherAppMainActivity添加代码
package com.example.otherappimport ....class OtherAppMainActivity : AppCompatActivity() {private val TAG = "AIDL-OtherAppMainActivity"private lateinit var binding : ActivityOtherAppMainBindingprivate lateinit var mServiceIntent: Intentprivate var mBinder : IAppAidlInterface? = nullprivate var mICount = 0//创建Service连接和断开的两个基础函数onServiceConnected()和onServiceDisconnected()private val connection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName?, service: IBinder?) {if(mBinder == null) {mBinder = IAppAidlInterface.Stub.asInterface(service)mICount++Log.v(TAG, "onServiceConnected() the time $mICount")try {val strData = "第 $mICount 次连接service成功"mBinder!!.setStringData(strData)} catch (e: RemoteException) {e.printStackTrace()}} else {mICount++Log.v(TAG, "mBinder is not null")}}override fun onServiceDisconnected(name: ComponentName?) {Log.v(TAG, "onServiceDisconnected")}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()binding = ActivityOtherAppMainBinding.inflate(layoutInflater)setContentView(binding.root)ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)insets}//新建intent来连接服务端mainapp,Intent的Component设置为Sevice的包名和类名mServiceIntent = Intent()mServiceIntent.component = ComponentName("com.example.mainapp", "com.example.mainapp.MainAppService")// 检查服务是否存在val resolveInfo = packageManager.resolveService(mServiceIntent, PackageManager.MATCH_DEFAULT_ONLY)if (resolveInfo != null) {// 服务存在,Intent有效Log.v(TAG, "Intent is valid")} else {// 服务不存在,Intent无效Log.v(TAG, "Intent is not valid")}//点击bind时与service绑定binding.bindServiceBtn.setOnClickListener {val bindResult = bindService(mServiceIntent, connection, Context.BIND_AUTO_CREATE)Log.v(TAG, "bindServiceBtn clicked bindResult:$bindResult")}//点击unbindg时与service解绑binding.unbindServiceBtn.setOnClickListener {Log.v(TAG, "unbindServiceBtn clicked")unbindService(connection)mBinder = null //把mBinder清空}}}
在otherapp里新建两个button用来控制bindService()和unbindService()
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".OtherAppMainActivity"><Buttonandroid:id="@+id/bindService"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Bind Service" /><Buttonandroid:id="@+id/unbindService"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Unbind Service" /></LinearLayout>
七、验证
把两个apk安装并启动:
点击bind会建立连接,点击ubind断开。再次点击bind计数会增加
测试结果:
2024-05-28 17:25:31.545 2285-2285 AIDL-Other...inActivity com.example.otherapp V Intent is valid
2024-05-28 17:25:34.879 2285-2285 AIDL-Other...inActivity com.example.otherapp V bindServiceBtn clicked bindResult:true
2024-05-28 17:25:34.882 1505-1505 AIDL-MainAppService com.example.mainapp V onCreate()
2024-05-28 17:25:34.891 2285-2285 AIDL-Other...inActivity com.example.otherapp V onServiceConnected() the time 1
2024-05-28 17:25:35.885 1505-2363 AIDL-MainAppService com.example.mainapp V mStrData:第 1 次连接service成功
2024-05-28 17:25:36.886 1505-2363 AIDL-MainAppService com.example.mainapp V mStrData:第 1 次连接service成功
2024-05-28 17:25:37.887 1505-2363 AIDL-MainAppService com.example.mainapp V mStrData:第 1 次连接service成功
2024-05-28 17:25:38.888 1505-2363 AIDL-MainAppService com.example.mainapp V mStrData:第 1 次连接service成功
2024-05-28 17:25:39.613 2285-2285 AIDL-Other...inActivity com.example.otherapp V unbindServiceBtn clicked
2024-05-28 17:25:39.621 1505-1505 AIDL-MainAppService com.example.mainapp V onUnbind()
2024-05-28 17:25:39.623 1505-1505 AIDL-MainAppService com.example.mainapp V onDestroy()
2024-05-28 17:25:39.888 1505-2363 AIDL-MainAppService com.example.mainapp V mStrData:第 1 次连接service成功
2024-05-28 17:25:42.022 2285-2285 AIDL-Other...inActivity com.example.otherapp V bindServiceBtn clicked bindResult:true
2024-05-28 17:25:42.024 1505-1505 AIDL-MainAppService com.example.mainapp V onCreate()
2024-05-28 17:25:42.037 2285-2285 AIDL-Other...inActivity com.example.otherapp V onServiceConnected() the time 2
2024-05-28 17:25:43.037 1505-2399 AIDL-MainAppService com.example.mainapp V mStrData:第 2 次连接service成功
2024-05-28 17:25:44.038 1505-2399 AIDL-MainAppService com.example.mainapp V mStrData:第 2 次连接service成功
2024-05-28 17:25:45.039 1505-2399 AIDL-MainAppService com.example.mainapp V mStrData:第 2 次连接service成功
2024-05-28 17:25:45.692 2285-2285 AIDL-Other...inActivity com.example.otherapp V unbindServiceBtn clicked
2024-05-28 17:25:45.701 1505-1505 AIDL-MainAppService com.example.mainapp V onUnbind()
2024-05-28 17:25:45.702 1505-1505 AIDL-MainAppService com.example.mainapp V onDestroy()
2024-05-28 17:25:46.040 1505-2399 AIDL-MainAppService com.example.mainapp V mStrData:第 2 次连接service成功