Kotlin进程通信------AIDL
Posted 战国剑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin进程通信------AIDL相关的知识,希望对你有一定的参考价值。
前篇介绍了进程通信中,串行通信的方式Messenger。但如果进程间,有多个方法要并行调用,那么Messenger就不合适使用,而应该使用AIDL方式。
Java方式的AIDL,在之前的文章中有介绍:Android远程接口之AIDL——Parcelable、in、out、inout简例
此处,主要将前文中的Java方式用Kotlin方式翻译。
AIDL方式通信,在Kotlin中遵循和Java中同样的规则,包括数据结构的限制,AIDL文件的编写。
一、AIDL文件编写
AIDL文件的编写,有特定的要求如下:
支持数据类型如下:
1. Java 的原生类型
2. String 和CharSequence
3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型; 以上三种类型都不需要导入(import)
4. AIDL 自定义生成的接口 需要导入(import)
————————————————
版权声明:本文为CSDN博主「战国剑」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yangzhaomuma/article/details/50576017
除基础类型外,如果我们要自定义类,需要手动导入(import),并且aidl文件和同名类文件的位置,有做要求:
以上图为例:
1、aidl文件夹与java文件夹,同层次
2、自定义的类,如果要在aidl中使用,有两个需要注意的地方:
2-1: 需要在java文件夹、aidl文件夹两处地方都做定义,并且包名需要一致,如图中的UserInfo类。
2-2: 如UserInfo这种在aidl中使用的自定义类,需要实现 Parcelable 接口。
了解以上规则,就用代码实现相应逻辑。
3、具体的AIDL文件如下(kotlin中,具体的aidl文件写法,还是java形式的):
3-1 IBase.aidl
// IBase.aidl
package com.me.kotlinprocess;
import com.me.kotlinprocess.aidl.UserInfo;
// Declare any non-default types here with import statements
interface IBase {
int add(int i,int j);
String getUserInfo(in UserInfo userInfo);
void getaList(out String[] list);
void setaList(in String[] list);
void gettList(inout String[] list);
}
3-2 UserInfo.aidl
// UserInfo.aidl
package com.me.kotlinprocess.aidl;
// Declare any non-default types here with import statements
parcelable UserInfo;
二、server端实现
server端,只需要实现service接口,并返回onBind的实现即可。此处IBase.Stub即是服务的实现。
kotlin中,服务的实现,应该是屏蔽了in、out 、inout参数的差异。此处生成的方法都是统一以out修饰。此处有疑议,如有不对请指出。
class AidlService : Service() {
override fun onBind(intent: Intent?): IBinder? {
return stub
}
val stub:IBase.Stub = object:IBase.Stub(){
override fun add(i: Int, j: Int): Int {
return i+j
}
override fun getUserInfo(userInfo: UserInfo?): String {
val resultString : String = "---- ${userInfo?.name} ${userInfo?.address} ${userInfo?.age} ----"
return resultString
}
override fun getaList(list: Array<out String>?) {
println("getaList ${list?.get(0)}")
}
override fun setaList(list: Array<out String>?) {
println("setaList ${list?.get(0)}")
}
override fun gettList(list: Array<out String>?) {
println("gettList ${list?.get(0)}")
}
}
}
三、client端实现
client端的实现,流程也很清晰。先连接上服务,之后,可通过接口调用具体的服务。
1、连接服务
var iBase: IBase? = null
//连接定义
private val serviceConnect = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
println("connect success")
iBase = IBase.Stub.asInterface(service)
}
override fun onServiceDisconnected(name: ComponentName?) {
println("connect fail")
iBase = null
}
}
//连接服务
bindService(
Intent(this, AidlService::class.java),
serviceConnect,
Context.BIND_AUTO_CREATE
)
2、调用服务
fun testAidl() {
val add = iBase?.add(1, 2)
println("add result $add")
val userInfo: UserInfo = UserInfo()
userInfo.name = "bob"
userInfo.address = "hangzhou"
userInfo.age = 20
val userInfo1 = iBase?.getUserInfo(userInfo)
println("userInfo result $userInfo1")
}
最后,别忘了在manifest中加上service的定义:
<service
android:name=".aidl.AidlService"
android:label="@string/aidl_name"
android:process=":aidl_remote">
</service>
至此,完成aidl的进程通信。
aidl的信息通信,主要的嘈点在于aidl文件编写和规范、连接管理较为繁琐。可以在这基础上,封装一套简易通信框架。期待后续。
以上是关于Kotlin进程通信------AIDL的主要内容,如果未能解决你的问题,请参考以下文章