当前位置: 首页 > news >正文

安卓Handler+Messenger实现跨应用通讯

一、服务端的实现

  1. 创建服务端的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 // 服务被杀死后自动重启}
}
  1. 在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可被“应用外部”启动或交互。

  1. 在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}
}
  1. 在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 解析等将不可见或返回空结果。

  1. 在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()
③ 建立连接 → 客户端绑定到服务端
④ 发送消息 → 客户端发送消息到服务端
⑤ 处理消息 → 服务端处理并回复
⑥ 接收回复 → 客户端接收服务端回复

四、实现结果

  1. 服务端

在这里插入图片描述

  1. 客户端

在这里插入图片描述

五、注意事项

  1. 服务端的Service在注册时android:exported="true"必不可少。
  2. Android 11+ 若跨应用,请在客户端 Manifest 加 使目标包可见。
  3. Messenger 跨进程不支持通过 obj 传递非 Parcelable 对象,必须用 Bundle(或 arg1/arg2/what)。
  4. Bundle 里只能放基础类型、String、Parcelable、Serializable。自定义对象请实现 Parcelable(@Parcelize)。大对象(如大 Bitmap)会触发 Binder 事务超限(约 1MB),避免放入 Bundle。
http://www.dtcms.com/a/427096.html

相关文章:

  • 公司网站建设完成通知重庆市工程建设交易中心网站
  • 北京网站设计公司hlh成都柚米科技15企业营销型网站系统
  • 德州网站建设招聘帝国网站怎么仿站
  • 15. C++ 类的转换
  • 基于STM32与influxDB的电力监控系统-7
  • python 之 argparse的简单使用
  • 开源 java android app 开发(十七)封库--混淆源码
  • windows显示驱动开发-IddCx 对象
  • 图书馆网站建设的作用广州新建站
  • (27)APS.NET Core8.0 堆栈原理通俗理解
  • SVN 一些命令疑问
  • 精读 C++20 设计模式:行为型设计模式 — 状态机模式
  • 多周期路径约束
  • Webpack配置之path.join、path.resolve和__dirname详解
  • vue打包优化方案都有哪些?
  • Golang 中的字符串:常见错误和最佳实践
  • 花生壳建设网站怎样做网络营销推广
  • 【Rust GUI开发入门】编写一个本地音乐播放器(8. 从文件中提取歌曲元信息)
  • 国内个人网站建设贾汪城乡建设局网站
  • CentOS二进制安装包方式部署K8S集群之系统初始化
  • Spring Boot 缓存集成实践
  • 力扣Hot100--21.合并两个有序链表
  • 网络安全和NLP、CV是并行的应用吗?
  • 如何做好一个企业网站专门做图片的网站
  • 网页设计网站wordpress公告栏插件
  • C++ 位运算 高频面试考点 力扣 371. 两整数之和 题解 每日一题
  • 网络安全常见敏感目录字典
  • React学习(三)--- 组件化开发编写css
  • 设计模式(C++)详解——观察者模式(Observer)(1)
  • 网站建设报表明细新手做网站看什么书