安卓Handler+Messenger实现跨应用通讯
一、服务端的实现
- 创建服务端的Service。
class MessengerService : Service() {companion object {const val MSG_SAY_HELLO = 1const val MSG_GET_DATA = 2const val MSG_SEND_DATA = 3}private val mMessenger = Messenger(IncomingHandler())inner class IncomingHandler : Handler(Looper.getMainLooper()) {override fun handleMessage(msg: Message) {when (msg.what) {MSG_SAY_HELLO -> {// 回复消息给客户端val text = msg.data?.getString("text")Log.d("MessengerService", "收到客户端消息: ${text}")val reply = Message.obtain(null, MSG_SAY_HELLO).apply {data = Bundle().apply { putString("reply", "服务端已收到: $text") }}msg.replyTo?.send(reply)}MSG_GET_DATA -> {// 处理获取数据请求val reply = Message.obtain(null, MSG_GET_DATA).apply {data = Bundle().apply { putString("result", "这是服务端的数据") }}msg.replyTo?.send(reply)}}super.handleMessage(msg)}}override fun onCreate() {super.onCreate()Log.d("MessengerService", "服务创建")}override fun onBind(intent: Intent): IBinder {Log.d("MessengerService", "服务绑定")return mMessenger.binder}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {Log.d("MessengerService", "服务启动")return START_STICKY // 服务被杀死后自动重启}
}
- 在AndroidManifest.xml中注册该Service。
<serviceandroid:name=".ui.activity.test.MessengerService"android:exported="true"><intent-filter><action android:name="cn.test.partner.MESSENGER_SERVICE" /></intent-filter></service>
其中android:exported="true"尤为关键,表示该Service可被“应用外部”启动或交互。
- 在Activity中启动Service.
// 启动MessengerServiceval intent = Intent(this, MessengerService::class.java)startService(intent)
二、客户端的实现
1.创建一个MessengerClient去实现和服务端的连接与通讯。
class MessengerClient {companion object {const val MSG_SAY_HELLO = 1const val MSG_GET_DATA = 2const val MSG_SEND_DATA = 3}private var mService: Messenger? = nullprivate var mReplyMessenger: Messenger? = nullprivate var mContext: Context? = nullprivate var mServiceConnection: ServiceConnection? = nullfun init(context: Context) {mContext = contextmReplyMessenger = Messenger(ReplyHandler())}fun connectToService() {val intent = Intent()intent.action = "cn.test.partner.MESSENGER_SERVICE"intent.setPackage("cn.test.partner") // 服务端应用的包名mServiceConnection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName?, service: IBinder?) {mService = Messenger(service)Log.d("MessengerClient", "连接服务成功")// 连接成功后可以发送消息sendHelloMessage()}override fun onServiceDisconnected(name: ComponentName?) {mService = nullLog.d("MessengerClient", "服务连接断开")}}mContext?.bindService(intent, mServiceConnection!!, Context.BIND_AUTO_CREATE)}fun sendHelloMessage() {val msg = Message.obtain(null, MSG_SAY_HELLO)msg.replyTo = mReplyMessengermsg.data = Bundle().apply {putString("text", "客户端发送: 你好服务端!")}try {mService?.send(msg)} catch (e: RemoteException) {e.printStackTrace()}}fun getData() {val msg = Message.obtain(null, MSG_GET_DATA)msg.replyTo = mReplyMessengermsg.data = Bundle().apply {putString("query", "need_data")}try {mService?.send(msg)} catch (e: RemoteException) {e.printStackTrace()}}inner class ReplyHandler : Handler(Looper.getMainLooper()) {override fun handleMessage(msg: Message) {val data = msg.data// 若服务端放了自定义 Parcelable,需要设置类加载器// data.classLoader = MyParcelable::class.java.classLoaderwhen (msg.what) {MSG_SAY_HELLO -> Log.d("MessengerClient", "服务端回复: ${data.getString("reply")}")MSG_GET_DATA -> Log.d("MessengerClient", "服务端数据: ${data.getString("result")}")}super.handleMessage(msg)}}fun disconnect() {mServiceConnection?.let {mContext?.unbindService(it)}mService = null}
}
- 在AndroidManifest.xml中注册queries
<queries><!-- 目标服务端应用包名 --><package android:name="cn.test.partner" /><!-- 或按组件可见性声明 --><intent><action android:name="cn.test.partner.MESSENGER_SERVICE" /></intent></queries>
是 Android 11(API 30)引入的清单节点,用于声明“应用可见的外部应用/组件”。它控制包可见性:没有在 (或其他允许途径)声明的目标应用,PackageManager 查询、隐式 Intent 解析等将不可见或返回空结果。
- 在Acitivity中初始化MessengerClient并和服务端进行连接。
private lateinit var messengerClient: MessengerClientoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)messengerClient = MessengerClient()messengerClient.init(this)messengerClient.connectToService()}override fun onDestroy() {super.onDestroy()messengerClient.disconnect()}
三、完整流程
① 启动服务端应用 → MessengerService 自动启动
② 启动客户端应用 → 调用 connectToService()
③ 建立连接 → 客户端绑定到服务端
④ 发送消息 → 客户端发送消息到服务端
⑤ 处理消息 → 服务端处理并回复
⑥ 接收回复 → 客户端接收服务端回复
四、实现结果
- 服务端
- 客户端
五、注意事项
- 服务端的Service在注册时android:exported="true"必不可少。
- Android 11+ 若跨应用,请在客户端 Manifest 加 使目标包可见。
- Messenger 跨进程不支持通过 obj 传递非 Parcelable 对象,必须用 Bundle(或 arg1/arg2/what)。
- Bundle 里只能放基础类型、String、Parcelable、Serializable。自定义对象请实现 Parcelable(@Parcelize)。大对象(如大 Bitmap)会触发 Binder 事务超限(约 1MB),避免放入 Bundle。