如何在原生App中调用Uniapp的原生功能?

简介: 如何在原生App中调用Uniapp的原生功能?

在原生 App 中调用 Uniapp 的“原生功能”,本质上是原生代码触发 Uniapp 中通过原生插件实现的功能(如 Uniapp 集成的相机、支付等原生能力),或调用 Uniapp 中定义的 JS 方法(间接触发其关联的原生逻辑)。核心是通过“原生与 Uniapp 的通信桥接”实现双向调用,以下分场景详细说明实现流程。

一、核心原理:原生与 Uniapp 的通信机制

Uniapp 与原生 App 的通信依赖桥接层(由 Uniapp SDK 提供),支持两种方向的调用:

  1. Uniapp 调用原生功能:通过 uni.requireNativePlugin 调用原生插件(Uniapp 官方或自定义插件)。
  2. 原生调用 Uniapp 功能:原生通过 SDK 提供的 API 发送事件或调用 JS 方法,触发 Uniapp 中对应的逻辑(包括其集成的原生功能)。

本文聚焦第 2 种场景:原生 App 主动触发 Uniapp 中已实现的原生功能(如 Uniapp 中封装的蓝牙扫描、地图定位等)。

二、场景1:原生调用 Uniapp 中通过官方插件实现的原生功能

Uniapp 官方提供了大量原生插件(如 uni.chooseImage 调用相机、uni.getLocation 获取定位),这些功能本质上是 Uniapp 封装的原生能力。原生 App 可通过调用 Uniapp 的 JS 方法间接触发这些功能。

实现步骤:

  1. Uniapp 端定义“触发原生功能的 JS 方法”
    在 Uniapp 页面中封装一个方法,内部调用官方插件的原生功能(如调用相机),并通过回调返回结果:

    // Uniapp 页面(pages/index/index.vue)
    export default {
         
      methods: {
         
        // 定义供原生调用的方法:触发相机功能
        triggerCamera(callback) {
         
          // 调用 Uniapp 官方插件的相机功能
          uni.chooseImage({
         
            count: 1,
            success: (res) => {
         
              callback({
          code: 0, data: res.tempFilePaths[0] }); // 返回照片路径
            },
            fail: (err) => {
         
              callback({
          code: 1, msg: err.errMsg });
            }
          });
        }
      },
      onLoad() {
         
        // 将方法挂载到 window,供原生调用
        window.triggerCamera = this.triggerCamera;
      }
    }
    
  2. 原生端调用 Uniapp 的 JS 方法
    通过 Uniapp SDK 提供的 API 执行 Uniapp 中挂载到 window 的方法,触发相机功能。

    • Android 原生调用
      使用 UniSDKEngine.evaluateJavascript 执行 JS 代码,调用 window.triggerCamera

      // 在原生 Activity 中
      String jsCode = "window.triggerCamera(function(res) { " +
          "window.NativeCallback.onCameraResult(JSON.stringify(res)); " + // 回调结果给原生
      "});";
      // 执行 JS 代码(需在主线程)
      runOnUiThread(() -> {
             
          UniSDKEngine.evaluateJavascript(jsCode, new UniSDKJSCallback() {
             
              @Override
              public void onReceiveValue(String value) {
             
                  // 可选:接收 JS 同步返回值
              }
          });
      });
      

      同时,原生需定义回调接口(NativeCallback)接收相机结果:

      // 注册全局回调对象,供 Uniapp JS 调用
      public class NativeCallbackModule extends UniModule {
             
          @UniJSMethod(uiThread = true)
          public void onCameraResult(String result) {
             
              // 解析 Uniapp 返回的照片路径
              JSONObject json = new JSONObject(result);
              String imagePath = json.getString("data");
              // 处理照片(如显示到原生 ImageView)
          }
      }
      
    • iOS 原生调用
      使用 DCUniSDKevaluateJavaScript 执行 JS 代码:

      // 在原生 ViewController 中
      NSString *jsCode = @"window.triggerCamera(function(res) { "
          @"window.webkit.messageHandlers.NativeCallback.postMessage(res); " // 回调给原生
      "});";
      [[DCUniSDK sharedInstance] evaluateJavaScript:jsCode completionHandler:^(id _Nullable result, NSError * _Nullable error) {
          // 可选:处理同步返回值
      }];
      

      通过 WKScriptMessageHandler 接收结果:

      // 实现 WKScriptMessageHandler 协议
      - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
          if ([message.name isEqualToString:@"NativeCallback"]) {
              NSDictionary *res = message.body;
              NSString *imagePath = res[@"data"]; // 处理照片路径
          }
      }
      

三、场景2:原生调用 Uniapp 中通过自定义插件实现的原生功能

若 Uniapp 集成了自定义原生插件(如团队自研的硬件交互插件),原生 App 需通过触发 Uniapp 中调用自定义插件的方法,间接使用该插件功能。

实现步骤:

  1. Uniapp 端封装自定义插件调用方法
    假设 Uniapp 集成了一个自定义蓝牙插件 BluetoothPlugin,封装方法供原生调用:

    // Uniapp 页面
    export default {
         
      methods: {
         
        // 调用自定义蓝牙插件扫描设备
        triggerBluetoothScan(callback) {
         
          const bluetoothPlugin = uni.requireNativePlugin('BluetoothPlugin');
          bluetoothPlugin.startScan({
          timeout: 5000 }, (res) => {
         
            callback(res); // 返回扫描结果
          });
        }
      },
      onLoad() {
         
        window.triggerBluetoothScan = this.triggerBluetoothScan; // 挂载到 window
      }
    }
    
  2. 原生端调用该方法
    与场景1类似,原生通过执行 JS 代码调用 window.triggerBluetoothScan

    • Android

      String jsCode = "window.triggerBluetoothScan(function(res) { " +
          "window.NativeCallback.onBluetoothResult(JSON.stringify(res)); " +
      "});";
      UniSDKEngine.evaluateJavascript(jsCode, null);
      
    • iOS

      NSString *jsCode = @"window.triggerBluetoothScan(function(res) { "
          @"window.webkit.messageHandlers.NativeCallback.postMessage(res); "
      "});";
      [[DCUniSDK sharedInstance] evaluateJavaScript:jsCode completionHandler:nil];
      

四、场景3:原生直接调用 Uniapp 插件的底层原生代码(进阶)

若自定义插件的原生代码(Android 的 Java/Kotlin、iOS 的 Objective-C/Swift)在原生 App 中可访问,可直接调用插件的底层方法,无需通过 Uniapp JS 中转(适合性能要求高的场景)。

实现条件:

  • 自定义插件的原生代码需以库(Library) 形式提供给原生 App(而非仅打包在 Uniapp 资源中)。
  • 原生 App 需依赖该插件的原生库,并了解其方法签名。

示例(Android):

假设 Uniapp 自定义插件 BluetoothPlugin 的原生代码中有一个 startScan 方法:

// 自定义插件的原生代码(BluetoothPlugin.java)
public class BluetoothPlugin extends UniModule {
   
    public void startScan(JSONObject params, UniJSCallback callback) {
   
        // 蓝牙扫描逻辑
    }
}

原生 App 若依赖了该插件的 AAR 包,可直接实例化并调用:

// 原生 App 中直接调用插件的原生方法
BluetoothPlugin bluetoothPlugin = new BluetoothPlugin();
JSONObject params = new JSONObject();
params.put("timeout", 5000);
bluetoothPlugin.startScan(params, new UniJSCallback() {
   
    @Override
    public void invoke(Object data) {
   
        // 处理扫描结果
    }
});

五、关键注意事项

  1. 通信时机:原生调用 Uniapp 功能前,需确保 Uniapp 页面已加载完成(可通过监听 Uniapp 的 onReady 事件确认),否则可能导致方法未定义。
  2. 线程安全:Android 中调用 evaluateJavascript 需在主线程,iOS 中需在主线程执行 UI 相关操作。
  3. 参数序列化:原生与 Uniapp 传递复杂参数(如对象、数组)时,需通过 JSON 序列化(JSON.stringify/JSON.parse),避免格式错误。
  4. 权限依赖:Uniapp 插件的原生功能(如相机、蓝牙)需在原生 App 中声明对应权限(如 Android 的 AndroidManifest.xml、iOS 的 Info.plist),否则调用会失败。
  5. 版本兼容性:Uniapp 插件版本需与原生 App 中集成的 SDK 版本匹配,避免因接口变更导致调用失败。

总结

原生 App 调用 Uniapp 的原生功能,本质是通过“原生 → Uniapp JS → Uniapp 插件”的调用链实现,核心依赖 Uniapp SDK 提供的 JS 桥接能力。具体方式需根据场景选择:

  • 简单场景:通过 evaluateJavascript 调用 Uniapp 中封装的 JS 方法,间接触发原生功能。
  • 进阶场景:若自定义插件原生代码可访问,直接调用其底层方法,减少通信开销。

通过这种方式,可充分复用 Uniapp 已实现的原生功能,避免原生 App 重复开发,同时保持两者的功能一致性。

相关文章
|
25天前
|
小程序 视频直播 数据安全/隐私保护
如何在1v1视频直播交友APP中实现防录屏防截屏功能?
婚恋交友市场快速增长,1v1社交应用海外投放增86.49%,中东、东南亚及北美需求旺盛。用户偏好私密高效交流,国内“云相亲”兴起。开发需合规备案、实名认证,并防范诈骗。本文详解原生APP防录屏技术:Android通过MediaProjection检测,iOS监听UIScreen状态,结合动态水印、远程销毁等增强防护,平衡体验与安全。
|
2月前
|
移动开发 小程序 Android开发
基于 uni-app 开发的废品回收类多端应用功能与界面说明
本文将对一款基于 uni-app 开发的废品回收类多端应用,从多端支持范围、核心功能模块及部分界面展示进行客观说明,相关资源信息也将一并呈现。
128 0
|
1月前
|
存储 自然语言处理 算法
参照Yalla、Hawa等主流APP核心功能,开发一款受欢迎的海外语聊需要从哪些方面入手
海外语聊APP开发需结合Yalla、Hawa等主流产品,聚焦多语言支持、实时音视频、社交互动与安全合规。兼顾技术架构、本地化运营与法律风险,避免劣质成品代码,平衡创新与成本,打造差异化出海产品。(239字)
|
3月前
|
存储 Java PHP
轻量化短视频电商直播带货APP源码全解析:核心功能与设计流程​
在电商直播热潮下,开发专属直播带货APP成为抢占市场关键。本文详解原生开发轻量化APP的核心功能与全流程设计,涵盖用户登录、商品浏览、直播互动、购物车、订单及售后功能,并介绍安卓端Java、苹果端Object-C、后台PHP的技术实现,助力打造高效优质的直播电商平台。
|
8月前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
432 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
5月前
|
数据库
《仿盒马》app开发技术分享-- 回收订单页功能完善(45)
上一节我们实现了订单的待取件、已取消状态展示,并且成功实现了修改订单状态后的列表刷新,实现了云端数据的修改,这一节我们来实现订单页剩下的两个板块的业务逻辑,分别是运输中、已完成状态下的列表展示以及订单状态的修改
117 1
|
4月前
|
存储 移动开发 监控
App Trace功能实战:一键拉起、快速安装与免提写邀请码的应用实践
App Trace系统通过一键拉起、快速安装和免提写邀请码三大功能,显著提升用户转化率、安装成功率和邀请注册率。结合深度技术实现与优化,助力公司用户增长,成为移动端核心基础设施。
|
5月前
|
UED
《仿盒马》app开发技术分享-- 扫一扫功能(35)
随着app的逐渐完善,我们现在需要在细节处做更多的打磨,在首页我们添加了很多静态的按钮和组件,现在我们开始对这些组件进行功能的添加,这次首先实现的是首页头部的扫一扫功能,扫一扫我们实现扫码后跳转商品详情页
126 0
|
5月前
|
存储 数据库
《仿盒马》app开发技术分享-- 购物车功能完善(14)
上一节我们实现了购物车商品列表的状态切换,已添加商品数量的增减,已添加商品滑动删除,已添加商品在选中情况下的价格计算。这一节我们在这些功能的基础上实现云端记录,因为我们现在只有数据的查询是从云端获取的,其他的操作虽然都实现了相对应的功能,但是当我们操作完,关闭app,再打开不会有对应的记录,有的同学可能会说,那我们把数据用首选项或者数据库的形式存储就可以了吧? 那如果我更换了另一个设备那这些添加的数据是不是就又不能使用了?所以我们的每个操作,最好都是提交到云端,这样我们在其他设备,在退出应用,切换账号这些情况下都能很好的保存我们操作后的购物车状态。
108 0
|
5月前
|
前端开发
《仿盒马》app开发技术分享-- 购物车基础功能实现(13)
上一节我们实现了加入购物车和购物车列表的简单展示。对一个电商类的应用来说,这很显然是不够的,我们的购物车内容应该更加的丰富,他需要用户能自主的去选择想要结算的商品,删除一些不需要的商品,或者取消掉一些本次不结算的商品,同时根据选择的不同,我们需要把相对应的价格和选择的数量等信息传递给用户,帮助用户节省更多的时间。
102 0

热门文章

最新文章