AIDL简介
什么是AIDL
AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写
AIDL有什么作用
对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP可以和其他APP交互。
什么场景下使用AIDL
AIDL更加适合在多个应用程序之间,多线程的情况下进行进程间通信
Binder更适合在多个应用程序之间,单线程都情况下进行进程间通信
Messenger更适合在只有进程间通信,单线程,单个应用程序中使用
使用AIDL
新建AIDL文件
首先,在Android Studio中项目那边有机,New-->Folder-->AIDL Folder
aidl目录跟java是同级的
aidl目录下新建对应都aidl文件
AIDL支持的数据类型
Android 开发网中有写
All primitive types in the Java programming language (such as int, long, char, boolean, and so on)
String
CharSequence
List
Map
虽然官方文档指明所有的java基础数据类型都是被支持的,但是实际上short并不支持,如果数据类型中含有short,则编译的时候会报以下错误:ERROR: xxx/IMyAidlInterface.aidl:15.38-43: Failed to resolve 'short'
需要注意的是Map不能够写泛型,如果写泛型的话,编译的时候会报以下错误:aidl E 08-31 17:11:09 17172 8244311 type_java.cpp:357] Don't know how to create a Map<K,V> container.
List虽然可以写泛型,但是泛型只能是上面提到的那些数据类型才行,类似于Integer也是不能被支持的,如果List的泛型是Integer,则编译的时候会报以下错误:ERROR: xxx/IMyAidlInterface.aidl:16.63-70: Failed to resolve 'Integer'
对于自定义的实现了Parcelable的数据类型也是可以支持的,但是必须建立一个.aidl文件声明你的parcelable类,例如
package top.xuqingquan.aidltest;
parcelable User;
对于所有非基本数据类型要求一个定向的tag来指定数据是去往哪个方向的,且只能是in、out、inout
以下是完整的aidl文件
// IMyAidlInterface.aidl
package top.xuqingquan.aidltest;
import java.util.List;
import java.util.Map;
import top.xuqingquan.aidltest.User;
interface IMyAidlInterface {
List<User> basicTypes(byte aByte,/*short aShort,*/ int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble,char aChar, String aString,in List<String> aList,in Map aMap,CharSequence aCharSequence,in User user);
}
服务端实现
新建一个Service,onBind方法返回的是一个实现刚才aidl的接口,具体代码如下:
package top.xuqingquan.aidltest
import android.app.Service
import android.content.Intent
import android.os.IBinder
class ITestAidlService : Service() {
private lateinit var users: MutableList<User?>
override fun onBind(p0: Intent?): IBinder {
users = arrayListOf()
return iBinder
}
private val iBinder: IBinder = object : IMyAidlInterface.Stub() {
override fun basicTypes(
aByte: Byte,
anInt: Int,
aLong: Long,
aBoolean: Boolean,
aFloat: Float,
aDouble: Double,
aChar: Char,
aString: String?,
aList: MutableList<String>?,
aMap: MutableMap<Any?, Any?>?,
aCharSequence: CharSequence?,
user: User?
): List<User?> {
users.add(user)
return users
}
}
}
客户端的实现
客户端需要将服务端的整个aidl目录下的内容全部复制一份,对于服务端有的User类,也需要在与服务端相同的包目录下定义剩下的就只需要使用bindService绑定Service,ServiceConnection的onServiceConnected可以拿到远程的aidl,这时候就可以使用它调用相关的方法了
package top.xuqingquan.aidlclienttest
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import kotlinx.android.synthetic.main.activity_main.*
import top.xuqingquan.aidltest.IMyAidlInterface
import top.xuqingquan.aidltest.User
class MainActivity : AppCompatActivity() {
private lateinit var iTestAidl: IMyAidlInterface
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//获取到服务端
val intent = Intent()
//Android 5.1开始必须显式intent启动service
intent.component =
ComponentName("top.xuqingquan.aidltest", "top.xuqingquan.aidltest.ITestAidlService")
bindService(intent, object : ServiceConnection {
override fun onServiceDisconnected(p0: ComponentName?) {
println("onServiceDisconnected")
}
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
println("onServiceConnected")
//拿到远程到aidl
iTestAidl = IMyAidlInterface.Stub.asInterface(p1)
}
}, Context.BIND_AUTO_CREATE)
tv_result.setOnClickListener {
try {
val list = iTestAidl.basicTypes(
0, 0, 0, false, 0f, 0.0, 'a', "", emptyList(),
emptyMap<Any, Any>(), "", User("test", 11)
)
tv_result.text = "${list.size}-$list"
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
}
最后,附上AIDL文档的地址:developer.android.google.cn/guide/compo…