(原创)使用Messenger进行轻量级跨进程通信

发布时间:2026/7/18 5:52:05
(原创)使用Messenger进行轻量级跨进程通信 安卓跨进程通信方式在安卓开发中其实有六大跨进程通信方式有的是我们经常用的有的用得少。分别是1.AIDL最常用、功能最强2.Binder底层核心所有 IPC 的底层都是 Binder3.ContentProvider专门给别的 APP 读数据4. BroadcastReceiver 广播5. Socket网络套接字6. Messenger最简单、轻量、基于 Handler、串行、单线程Messenger如何实现跨进程通信Messenger其实是通过handler来通信的因为handler是一条一条消息发过来并处理。所以是串行的下面从客户端和服务端分别介绍如何通信服务端服务端一般是一个service需要创建一个信使也就是MessengerprivatevalserviceMessengerMessenger(serviceHandler)在onbind方法中把这个信使的binder返回回去overridefunonBind(intent:Intent):IBinder{returnserviceMessenger.binder}方便客户端使用信使的创建的时候构造方法里面需要一个handler这个handler就是用来接收并且处理另外一端发来的消息具体代码下面源码都有客户端一样的客户端也需要一个客户端的信使和自己用来处理消息的handlerprivatevalclientMessengerMessenger(clientHandler)在绑定服务端的service中可以拿到服务端的信使overridefunonServiceConnected(name:ComponentName,service:IBinder){// 绑定成功获取服务端信使serverMessengerMessenger(service)isBindtrueToast.makeText(thisMainActivity,绑定远程服务成功,Toast.LENGTH_SHORT).show()}这样客户端就可以用服务端的信使发消息给服务端// 发送消息到远程服务// 点击按钮发送消息funsendMsg(view:View?){if(!isBind||serverMessengernull)returntry{valmsgMessage.obtain(null,1001)valbundleBundle()bundle.putString(obj_client,你好服务端)msg.databundle// msg.obj 你好服务端 //不可以用obj进行跨进程传递对象数据哪怕是string系统会认为数据没有序列化然后报错// 携带自己的信使让服务端可以回复msg.replyToclientMessenger// 发送消息到远程服务serverMessenger!!.send(msg)}catch(e:RemoteException){e.printStackTrace()}}发送的时候客户端通过replyTo 字段把自己端的信使传递给服务端这样服务端拿到客户端的信使就可以发消息给客户端msg.replyToclientMessenger相当于两端都各自拿到对面的信使就可以进行通信最后如果要解绑服务记得释放服务端的信使避免内存泄漏serverMessengernull页面退出也记得移除handler的消息// 清空Handler防泄漏clientHandler.removeCallbacksAndMessages(null);Messenger对比AIDL相同点1.都与IPC的调用有关2.Messenger 是一种轻量级的 IPC方案底层实现了AIDL只是进行了封装开发的时候不用再写.aidl文件。3.都支持实时通信不同点1.Messenger一次只能处理一个请求串行/AIDL一次可以处理多个请求并行2.Messenger不支持RPC只能通过message传递消息/AIDL支持RPC3.Messenger使用简单轻量级不需要创建AIDL文件/AIDL使用复杂需要创建AIDL文件源码Activityimportandroid.content.ComponentNameimportandroid.content.Intentimportandroid.content.ServiceConnectionimportandroid.os.Bundleimportandroid.os.Handlerimportandroid.os.IBinderimportandroid.os.Looperimportandroid.os.Messageimportandroid.os.Messengerimportandroid.os.RemoteExceptionimportandroid.view.Viewimportandroid.widget.Toastimportandroidx.activity.enableEdgeToEdgeimportandroidx.appcompat.app.AppCompatActivityimportandroidx.core.view.ViewCompatimportandroidx.core.view.WindowInsetsCompatclassMainActivity:AppCompatActivity(){// 客户端Handler接收并处理服务端回复privatevalclientHandler:Handlerobject:Handler(Looper.getMainLooper()){overridefunhandleMessage(msg:Message){super.handleMessage(msg)if(msg.what2001){valbundlemsg.datavalresultbundle.getString(obj_server)Toast.makeText(thisMainActivity,客户端收到回复$result,Toast.LENGTH_SHORT).show()}}}// 服务端信使用于发送消息给服务端privatevarserverMessenger:Messenger?null// new Messenger(clientHandler) 把客户端Handler包装成信使用于接收服务端消息privatevalclientMessengerMessenger(clientHandler)//绑定状态privatevarisBindfalse// 服务连接privatevalconnection:ServiceConnectionobject:ServiceConnection{overridefunonServiceConnected(name:ComponentName,service:IBinder){// 绑定成功获取服务端信使serverMessengerMessenger(service)isBindtrueToast.makeText(thisMainActivity,绑定远程服务成功,Toast.LENGTH_SHORT).show()}overridefunonServiceDisconnected(name:ComponentName){Toast.makeText(thisMainActivity,取消绑定远程服务成功,Toast.LENGTH_SHORT).show()isBindfalseserverMessengernull}}overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)enableEdgeToEdge()setContentView(R.layout.activity_main)ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)){v,insets-valsystemBarsinsets.getInsets(WindowInsetsCompat.Type.systemBars())v.setPadding(systemBars.left,systemBars.top,systemBars.right,systemBars.bottom)insets}// 绑定服务bindService()}// 绑定服务privatefunbindService(){valintentIntent(this,RemoteService::class.java)bindService(intent,connection,BIND_AUTO_CREATE)}// 点击按钮发送消息funsendMsg(view:View?){if(!isBind||serverMessengernull)returntry{valmsgMessage.obtain(null,1001)valbundleBundle()bundle.putString(obj_client,你好服务端)msg.databundle// msg.obj 你好服务端 //不可以用obj进行跨进程传递对象数据哪怕是string系统会认为数据没有序列化然后报错// 携带自己的信使让服务端可以回复msg.replyToclientMessenger// 发送消息到远程服务serverMessenger!!.send(msg)}catch(e:RemoteException){e.printStackTrace()}}overridefunonDestroy(){super.onDestroy()// 解绑服务if(isBind){unbindService(connection)isBindfalse}// 清空Handler防泄漏clientHandler.removeCallbacksAndMessages(null);}}Serviceimportandroid.app.Serviceimportandroid.content.Intentimportandroid.os.Bundleimportandroid.os.Handlerimportandroid.os.IBinderimportandroid.os.Looperimportandroid.os.Messageimportandroid.os.Messengerimportandroid.os.RemoteExceptionimportandroid.widget.ToastclassRemoteService:Service(){privatevalserviceHandlerHandler(Looper.getMainLooper()){msg-//客户端信使valclientMessengermsg.replyTovalbundlemsg.datavalcontentbundle.getString(obj_client)when(msg.what){1001-{Toast.makeText(thisRemoteService,服务端收到$content,Toast.LENGTH_SHORT).show()try{valreplyMsgMessage.obtain(null,2001)valbundleBundle()bundle.putString(obj_server,服务端已收到已处理完毕)replyMsg.databundle// msg.obj 服务端已收到已处理完毕 //不可以用obj进行跨进程传递对象数据哪怕是string系统会认为数据没有序列化然后报错clientMessenger.send(replyMsg)}catch(e:RemoteException){e.printStackTrace()}}}true}//服务端信使privatevalserviceMessengerMessenger(serviceHandler)overridefunonBind(intent:Intent):IBinder{returnserviceMessenger.binder}}xml里面写个button就可以?xml version1.0encodingutf-8?androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:idid/mainandroid:layout_widthmatch_parentandroid:layout_heightmatch_parenttools:context.MainActivityButtonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:onClicksendMsgandroid:textHello World!app:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent//androidx.constraintlayout.widget.ConstraintLayout最后记得配置清单注册!--远程服务单独进程--serviceandroid:name.RemoteServiceandroid:process:remote/