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

Uniapp——安卓与Uniapp数据通信交互

原生向Uniapp通信

  • UniApp 安卓自定义基座:Android 原生与 UniApp 双向通信完整方案
    • 一、先理解几个核心概念
      • 1. `globalEvent` 是什么?
      • 2. `mUniSDKInstance` 是哪里来的?
      • 3. `UniModule` 和 `UniDestroyableModule` 区别
    • 二、整体通信架构
    • 三、完整代码示例
    • 1. 全局保存 UniSDKInstance:`UniInstanceHolder.java`
    • 2. 自定义原生插件:`NativeBridgeModule.java`
    • 3. Android Activity 主动发送消息:`NativeActivity.java`
    • 4. 注册原生插件:`dcloud_uniplugins.json`
    • 5. UniApp 页面使用
    • 四、为什么 `uni.requireNativePlugin('globalEvent')` 不会创建 Module 实例?
    • 五、Activity 里能不能直接用 `mUniSDKInstance`?
    • 六、能不能用 EventBus?
    • 七、重要注意事项
      • 1. 必须先监听,再发送
      • 2. 必须先绑定 `mUniSDKInstance`
      • 3. `globalEvent` 只适合当前页面
      • 4. 不要强引用 `UniSDKInstance`
      • 5. 关键业务数据建议缓存后主动读取
    • 八、推荐使用场景
    • 九、最终结论
    • 参考文档

UniApp 安卓自定义基座:Android 原生与 UniApp 双向通信完整方案

在 UniApp 安卓自定义基座开发中,经常会遇到一个需求:

Android 原生层拿到数据之后,如何传给 UniApp 页面?同时 UniApp 页面又如何给 Android 原生发送消息?

比如这些场景:

  • 原生登录 SDK 回调登录结果
  • 原生支付页面返回支付状态
  • Android Activity 处理完业务后通知 UniApp
  • UniApp 页面主动调用 Android 原生能力
  • 原生 SDK 异步回调后需要通知前端页面刷新状态

本文整理一套比较完整的双向通信方案:

Android -> UniApp:globalEvent + fireGlobalEventCallback UniApp -> Android:uni.requireNativePlugin + 自定义 UniModule 方法

需要注意的是,globalEvent不是你自己写的原生插件 Module,它只是 UniApp JS 侧的内置事件监听对象。真正能拿到mUniSDKInstance的,是你自己写的UniModuleUniDestroyableModule


一、先理解几个核心概念

1.globalEvent是什么?

globalEvent是 UniApp App 端内置的全局事件监听对象。

UniApp 页面可以这样监听 Android 原生发来的事件:

constglobalEvent=uni.requireNativePlugin('globalEvent')globalEvent.addEventListener('native_event',e=>{console.log('收到 Android 消息:',JSON.stringify(e))})

但是它只负责 JS 侧监听,不会创建你的 Android Module 实例。

也就是说:

uni.requireNativePlugin('globalEvent')

拿到的是 DCloud 内置事件监听对象,不是你自己的NativeBridgeModule


2.mUniSDKInstance是哪里来的?

mUniSDKInstanceUniModule父类提供的当前页面实例。

只有你的类继承了:

UniModule

或:

UniDestroyableModule

才可以直接使用:

mUniSDKInstance

例如:

publicclassNativeBridgeModuleextendsUniModule{@UniJSMethod(uiThread=true)publicvoidsendEvent(){mUniSDKInstance.fireGlobalEventCallback("native_event",params);}}

如果代码写在下面这些地方,是没有mUniSDKInstance的:

ActivityApplicationServiceBroadcastReceiver普通工具类SDK回调类

这也是很多人找不到mUniSDKInstance的原因。


3.UniModuleUniDestroyableModule区别

作用适合场景
UniModule普通原生 Module一次性调用、获取数据、打开页面
UniDestroyableModule带销毁生命周期的 ModuleEventBus 注册、监听器、定位、蓝牙、SDK 回调等需要释放的场景

如果只是简单调用:

getToken(callback)

UniModule就可以。

如果你有:

EventBus.register(this)BroadcastReceiver注册Handler延迟任务SDK监听回调Dialog/Popup持有Activity

建议使用:

UniDestroyableModule

因为它可以在destroy()中释放资源。


二、整体通信架构

推荐结构如下:

UniApp 页面 | | uni.requireNativePlugin('NativeBridge') v NativeBridgeModule | | 保存 mUniSDKInstance v UniInstanceHolder | | Activity / SDK 回调调用 fireEvent v mUniSDKInstance.fireGlobalEventCallback(...) | v UniApp globalEvent.addEventListener(...)

双向通信关系:

UniApp -> Android: nativeBridge.sendMessageToAndroid(params, callback) Android -> UniApp: mUniSDKInstance.fireGlobalEventCallback("native_event", data) Android -> UniApp 页面监听: globalEvent.addEventListener("native_event", callback)

三、完整代码示例

下面示例实现两个方向:

  1. UniApp 主动给 Android 发送消息
  2. Android Activity 主动给 UniApp 页面发送消息

1. 全局保存 UniSDKInstance:UniInstanceHolder.java

不要直接用:

publicstaticUniSDKInstanceinstance;

因为UniSDKInstance绑定的是当前页面实例,直接静态强引用容易导致页面泄漏、旧页面收到事件、事件发错页面。

建议用WeakReference

packagecom.xxx.uniplugin;importandroid.os.Handler;importandroid.os.Looper;importjava.lang.ref.WeakReference;importjava.util.Map;importio.dcloud.feature.uniapp.UniSDKInstance;publicclassUniInstanceHolder{privatestaticWeakReference<UniSDKInstance>instanceRef;publicstaticvoidbind(UniSDKInstanceinstance){instanceRef=newWeakReference<>(instance);}publicstaticvoidclear(UniSDKInstanceinstance){if(instanceRef!=null&&instanceRef.get()==instance){instanceRef.clear();instanceRef=null;}}publicstaticvoidfireEvent(StringeventName,Map<String,Object>data){if(instanceRef==null)return;UniSDKInstanceinstance=instanceRef.get();if(instance==null)return;newHandler(Looper.getMainLooper()).post(()->{instance.fireGlobalEventCallback(eventName,data);});}}

2. 自定义原生插件:NativeBridgeModule.java

这个 Module 负责:

  • 绑定当前页面的mUniSDKInstance
  • 接收 UniApp 发来的消息
  • 回调结果给 UniApp
  • 测试 Android 主动发送事件给 UniApp
  • 页面销毁时清理实例
packagecom.xxx.uniplugin;importcom.alibaba.fastjson.JSONObject;importjava.util.HashMap;importjava.util.Map;importio.dcloud.feature.uniapp.annotation.UniJSMethod;importio.dcloud.feature.uniapp.bridge.UniJSCallback;importio.dcloud.feature.uniapp.common.UniDestroyableModule;publicclassNativeBridgeModuleextendsUniDestroyableModule{@UniJSMethod(uiThread=true)publicvoidbindUniInstance(){UniInstanceHolder.bind(mUniSDKInstance);}@UniJSMethod(uiThread=true)publicvoidunbindUniInstance(){UniInstanceHolder.clear(mUniSDKInstance);}/** * UniApp 主动给 Android 发送消息 */@UniJSMethod(uiThread=true)publicvoidsendMessageToAndroid(JSONObjectparams,UniJSCallbackcallback){Stringtype=params.getString("type");Stringcontent=params.getString("content");android.util.Log.e("NativeBridge","type = "+type);android.util.Log.e("NativeBridge","content = "+content);if(callback!=null){JSONObjectresult=newJSONObject();result.put("code",0);result.put("msg","Android 已收到 UniApp 消息");result.put("receiveType",type);result.put("receiveContent",content);callback.invoke(result);}}/** * Android 主动发送事件给 UniApp */@UniJSMethod(uiThread=true)publicvoidtestSendEventToUniApp(){Map<String,Object>data=newHashMap<>();data.put("type","android_event");data.put("msg","这是 Android 主动发送给 UniApp 的消息");UniInstanceHolder.fireEvent("native_event",data);}@Overridepublicvoiddestroy(){UniInstanceHolder.clear(mUniSDKInstance);super.destroy();}}

3. Android Activity 主动发送消息:NativeActivity.java

如果你是在 Activity 中拿到了数据,比如登录结果、支付结果、页面选择结果,可以这样通知 UniApp:

packagecom.xxx.uniplugin;importandroid.app.Activity;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;importjava.util.HashMap;importjava.util.Map;publicclassNativeActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);Buttonbutton=newButton(this);button.setText("发送数据给 UniApp");button.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewview){sendDataToUniApp();}});setContentView(button);}privatevoidsendDataToUniApp(){Map<String,Object>data=newHashMap<>();data.put("type","activity_result");data.put("token","abc123");data.put("userId","10001");UniInstanceHolder.fireEvent("native_event",data);}}

4. 注册原生插件:dcloud_uniplugins.json

注意:name要和前端的uni.requireNativePlugin('NativeBridge')保持一致。

{"nativePlugins":[{"plugins":[{"type":"module","name":"NativeBridge","class":"com.xxx.uniplugin.NativeBridgeModule"}]}]}

如果是自定义基座,需要重新打包自定义基座。


5. UniApp 页面使用

<template> <view class="page"> <button @click="sendToAndroid">UniApp 发消息给 Android</button> <button @click="androidSendToUniApp">测试 Android 发消息给 UniApp</button> <view class="title">结果:</view> <text>{{ result }}</text> </view> </template> <script> const globalEvent = uni.requireNativePlugin('globalEvent') const nativeBridge = uni.requireNativePlugin('NativeBridge') export default { data() { return { result: '' } }, onLoad() { // Android -> UniApp globalEvent.addEventListener('native_event', e => { console.log('收到 Android 主动消息:', JSON.stringify(e)) this.result = JSON.stringify(e) }) // 绑定当前页面对应的 mUniSDKInstance nativeBridge.bindUniInstance() }, onUnload() { nativeBridge.unbindUniInstance() }, methods: { // UniApp -> Android sendToAndroid() { nativeBridge.sendMessageToAndroid( { type: 'user_click', content: '用户点击了按钮' }, res => { console.log('Android 返回:', JSON.stringify(res)) this.result = JSON.stringify(res) } ) }, // 测试 Android -> UniApp androidSendToUniApp() { nativeBridge.testSendEventToUniApp() } } } </script>

四、为什么uni.requireNativePlugin('globalEvent')不会创建 Module 实例?

因为globalEvent是 DCloud 内置事件监听模块,不是你自己注册的插件。

下面这句:

constglobalEvent=uni.requireNativePlugin('globalEvent')

只是在 JS 侧拿到事件监听对象,用来:

globalEvent.addEventListener('native_event',callback)

它不会创建你的:

NativeBridgeModule

真正创建你自定义 Module 的是:

constnativeBridge=uni.requireNativePlugin('NativeBridge')

前提是你已经在dcloud_uniplugins.json中注册:

{"type":"module","name":"NativeBridge","class":"com.xxx.uniplugin.NativeBridgeModule"}

五、Activity 里能不能直接用mUniSDKInstance

不能直接用。

因为 Activity 并不继承UniModule,所以它没有mUniSDKInstance

错误理解:

publicclassNativeActivityextendsActivity{// 这里没有 mUniSDKInstance}

正确做法:

UniModule 拿到 mUniSDKInstance ↓ 保存到 UniInstanceHolder ↓ Activity 通过 UniInstanceHolder.fireEvent(...) ↓ UniApp 通过 globalEvent 收到

六、能不能用 EventBus?

可以。

但 EventBus 只能解决 Android 原生层内部通信,不能直接把数据发到 UniApp JS。

正确结构应该是:

Activity / SDK 回调 ↓ EventBus.post(...) ↓ NativeBridgeModule 接收事件 ↓ mUniSDKInstance.fireGlobalEventCallback(...) ↓ UniApp globalEvent 收到

也就是说:

  • EventBus 是 Android 内部消息通道
  • globalEvent才是 Android 通知 UniApp 的通道
  • mUniSDKInstance仍然是最终发送事件的关键

如果业务是登录结果、支付结果这种“不允许丢”的数据,也可以用postSticky,或者更稳一点:原生先缓存,UniApp 页面加载后主动读取。


七、重要注意事项

1. 必须先监听,再发送

UniApp 页面必须先执行:

globalEvent.addEventListener('native_event',callback)

然后 Android 再发送:

fireGlobalEventCallback("native_event",data)

如果 Android 发送太早,事件会丢。


2. 必须先绑定mUniSDKInstance

页面加载后要调用:

nativeBridge.bindUniInstance()

否则 Activity 通过UniInstanceHolder.fireEvent(...)时,没有可用的页面实例。


3.globalEvent只适合当前页面

globalEvent是通过当前页面的UniSDKInstance发送事件,所以更适合当前页面接收。

如果你的 App 有多个页面,或者页面切换频繁,需要特别注意:

  • 当前保存的是不是最新页面实例
  • 旧页面销毁时有没有清理
  • 事件是否可能发给错误页面

4. 不要强引用UniSDKInstance

不推荐:

publicstaticUniSDKInstanceinstance;

推荐:

privatestaticWeakReference<UniSDKInstance>instanceRef;

并在destroy()中清理:

UniInstanceHolder.clear(mUniSDKInstance);

5. 关键业务数据建议缓存后主动读取

如果是下面这些数据:

  • 登录结果
  • 支付结果
  • SDK 初始化结果
  • 广告归因结果
  • 启动参数

不建议完全依赖globalEvent

更稳的方式是:

Android 先缓存数据 ↓ UniApp 页面 onLoad / onShow ↓ 主动调用 nativeBridge.getPendingData(...) ↓ Android 通过 callback 返回数据

因为globalEvent有监听时机问题,一旦页面没有准备好,事件就可能丢。


八、推荐使用场景

场景推荐方案
UniApp 主动调用原生能力NativeBridgeModule + UniJSCallback
Android 主动通知当前页面globalEvent + fireGlobalEventCallback
Activity 给 UniApp 发实时事件UniInstanceHolder + globalEvent
Service / SDK 回调通知页面EventBus + NativeBridgeModule + globalEvent
登录、支付等不能丢的数据原生缓存 + UniApp 主动读取
长时间监听定位、蓝牙、传感器UniDestroyableModule管理生命周期

九、最终结论

UniApp 安卓自定义基座里,原生与 UniApp 双向通信可以这样理解:

UniApp -> Android: 调用自定义 NativeBridgeModule 方法 Android -> UniApp: 通过 mUniSDKInstance.fireGlobalEventCallback 发送 globalEvent Activity 里没有 mUniSDKInstance: 需要通过 UniModule 绑定后间接使用

最推荐的整体方案是:

UniApp 页面 addEventListener ↓ UniApp 调 bindUniInstance ↓ UniModule 保存当前 mUniSDKInstance ↓ Activity / SDK 回调通过 Holder 或 EventBus 通知 ↓ UniModule / Holder 调 fireGlobalEventCallback ↓ UniApp 收到事件

如果只是实时通知,这套方案可以使用。

如果是关键业务结果,比如登录、支付、归因,建议增加一层缓存,让 UniApp 主动读取,避免事件丢失。


参考文档

  • uni.requireNativePlugin 官方文档
  • DCloud Android 原生插件开发文档
  • DCloud UniMP Android 扩展开发文档
http://www.jsqmd.com/news/1145345/

相关文章:

  • 企业级AI Agent架构长啥样?一张图看懂!
  • LeetCode 1288. 删除被覆盖区间
  • 数据不丢、服务不断:政策快报平台的冷备与灾备实践
  • 从数据沼泽到情报中枢:招投标信息平台的技术架构演进路径分析
  • 上了排产系统半年,计划员为什么还在偷偷用Excel?JVS-APS智能排产与您聊聊原因
  • 从AIGC到AIGS的范式转变
  • Alexa Fluor系列蛋白荧光标记一站式定制
  • BEVFormer 可形变注意力解析:对比3种注意力机制,计算效率提升40%
  • 私域流量破局:如何利用微信机器人开发工具实现外部群的主动调用与群控?
  • Transmission Remote GUI终极指南:跨平台远程BT下载管理神器
  • MySQL 库表操作 +数据类型+ 基础概念全梳理
  • PHILIPS 459800312933 通讯模块
  • 2026年八字排盘软件推荐:AI提示词、多盘复盘和真太阳时功能怎么选?
  • 激光共聚焦显微镜在精密制造中3D表面形貌测量的核心技术
  • 2026广州做小程序商城的公司有哪些
  • B站视频转换终极指南:5分钟拯救你的珍贵缓存视频
  • 虚拟角色AI助手开发指南:从设定到工程化实现
  • Final Cut Pro 12.3 重磅更新!端侧AI自动字幕+智能遮罩+剪辑还原
  • 【Linux基础IO】printf 为什么会写进文件?一文搞懂重定向和 dup2 底层原理
  • 皮肤病肿瘤区域分割数据集:438张训练图+145张测试图,带高清mask与一键可视化脚本
  • OpenCV 4.8 + Python 圆孔尺寸测量实战:MindVision相机标定与0.01mm精度实现
  • 怎么做抖音?8人团队单月获客100+的秘密!
  • 多品牌珠宝集团一体化售后数字化落地分析:单套系统能否覆盖品牌区分、会员打通、维保自动提醒
  • 2026外贸建站公司哪家好
  • 2026年7月本地化AI搜索引擎优化策略
  • 当 AI 什么都会做,人还需要做什么?
  • Token计算深度分解:搞懂大模型的“计价单位”
  • AI Research OS:将Obsidian笔记转化为智能体长期记忆的完整实践
  • 2026网站建设公司推荐
  • ViGEmBus虚拟手柄驱动实战:为什么它是Windows游戏玩家的必备方案?