Android
跨进程通信有很多种方式, 具体的大家百度一下就知道了. AIDL
就是其中一种;
本文介绍AIDL
系统轻量封装Messager
的使用.
官网文档:https://developer.android.google.cn/guide/components/bound-services邀请您先阅读
涉及到的类
类名 | 作用 |
---|---|
Service | 进程载体 |
Handler | 处理消息, 关联Message 和Messenger 的通道 |
Message | 需要发送的消息实体 , 传输数据 的载体 |
Messenger | 发送消息, 通信的实体类, 用来send Message |
Parcelable | 自定义需要传输的数据 |
1.服务端编写
class RemoteService : Service() {
val remoteHandler: Handler = object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
//注意此处, 必须的设置, 否则自定义的MsgBean类, ClassNotFoundException异常
msg.data.classLoader = RemoteService.javaClass.classLoader
val bean:MsgBean = msg.data.getParcelable<MsgBean>("data")
if (msg.what == 3) {
//测试死循环, 不会出现anr
Thread.sleep(10_000)
}
//收到消息后, 可以通过replyTo对象, 回复客户端.
msg.replyTo?.let {
//java.lang.RuntimeException: Can't marshal callbacks across processes.
// it.send(Message.obtain(null) {
// L.e("runnable")
// })
sendText(it, 10_001, "服务端已收到消息.${msg.what}")
}
}
}
private fun sendText(messenger: Messenger, what: Int, text: String) {
messenger.send(Message.obtain(null, what).apply {
replyTo = remoteMessenger //用来答复的Messenger
data = Bundle().apply {
putParcelable("data", MsgBean(text)) //数据建议放在 Bundle中
}
})
}
private val remoteMessenger: Messenger
init {
remoteMessenger = Messenger(remoteHandler)
}
override fun onBind(p0: Intent?): IBinder {
return remoteMessenger.binder
}
}
几点需要注意的:
1. 静态数据在服务端修改后, 客户端获取不到修改后的值
2. 自定义的数据, 尽量使用 Bundle
包一层
3. Bundle
需要设置classLoader
, 否则会出现ClassNotFoundException
不要忘了在AndroidManifest.xml
声明:
<service
android:name=".RemoteService"
android:process=":remote"/>
如果
android:process
的名字, 有:
号, 则这个进程和主进程是父子关系
否则就是兄弟关系
2.客户端编写
基础的对象声明:
val localHandler = object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
L.e("客户端: handleMessage ->${RemoteService.test_static_data} ${msg.what} ${msg.obj}")
msg.data.classLoader = classLoader //注意:同样的设置
showText("收到服务端消息:${RemoteService.test_static_data} ${msg.what} ${msg.obj} ${msg.data.getParcelable<MsgBean>("data")}")
}
}
val localMessenger = Messenger(localHandler)
var remoteMessenger: Messenger? = null
启动服务端:
val remoteServiceIntent = Intent(this, RemoteService::class.java)
val remoteCon = object : ServiceConnection {
override fun onServiceDisconnected(p0: ComponentName?) {
L.e("call: onServiceDisconnected -> $p0")
showText("onServiceDisconnected_${p0}")
remoteMessenger = null
}
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
L.e("call: onServiceConnected -> $p0 $p1")
showText("onServiceConnected_${p0}")
remoteMessenger = Messenger(p1)
sendText(1, "客户端连接成功...")
}
}
bindService(remoteServiceIntent, remoteCon, Service.BIND_AUTO_CREATE)
发送消息:
private fun sendText(what: Int, text: String) {
remoteMessenger?.send(Message.obtain(null, what).apply {
replyTo = localMessenger
data = Bundle().apply {
putParcelable("data", MsgBean(text)) //用Bundle包一层
}
})
}
源码地址: https://github.com/angcyo/IPC_Messager
也许你还想学习更多, 来我的群吧, 我写代码的能力, 远大于写文章的能力:
联系作者
请使用QQ扫码加群, 小伙伴们都在等着你哦!
关注我的公众号, 每天都能一起玩耍哦!