参考资料: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.mainapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log
class 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 = true
override 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 = true
Thread {
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 = false
return super.onUnbind(intent)
}
override fun onDestroy() {
super.onDestroy()
Log.v(TAG, "onDestroy()")
}
}
需要确保mainappservice在AndroidMainfiest.xml里添加了Service标签
<application
android: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">
<service
android:name=".MainAppService"
android:enabled="true"
android:exported="true">
</service>
<!-- .... -->
</application>
六、OtherApp里OtherAppMainActivity添加代码
package com.example.otherapp
import ....
class OtherAppMainActivity : AppCompatActivity() {
private val TAG = "AIDL-OtherAppMainActivity"
private lateinit var binding : ActivityOtherAppMainBinding
private lateinit var mServiceIntent: Intent
private var mBinder : IAppAidlInterface? = null
private 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">
<Button
android:id="@+id/bindService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bind Service" />
<Button
android: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成功