文章目录
前言
在 uni-app 中适配 App 平台(即打包生成 iOS/Android 原生应用)时,使用的是一种混合开发架构(Hybrid App Runtime),其核心是:
✅ 1. App 使用的 Runtime 架构:WebView + 原生容器(plus runtime)
📌 技术栈核心:
- 前端代码运行在 WebView 中(HTML + CSS + JS 渲染);
- 原生能力(摄像头、定位、蓝牙、支付等)通过
plus.*
API 调用; - Web 层与 Native 层之间通过 JSBridge 通信机制 实现双向调用;
这类架构被称为“HTML5+ Runtime”,是 DCloud 自研的一种 增强型 WebView 容器。
✅ 2. WebView + Native 的通信机制详解(JSBridge)
📤 Web → Native 调用(JS 调原生)
- 使用
plus.xxx
(如plus.camera.getCamera()
)来发起调用; - DCloud 注入了
plus
对象到 WebView 的 JS 全局作用域; - JS 触发调用 → Native 捕捉到请求 → 执行原生功能 → 可异步返回结果到 JS。
📥 Native → Web 回调
- 原生模块执行完成后,通过
evalJS()
或postMessage()
回调到 Web; - uni-app 框架统一管理回调,开发者通常不需要手动维护 bridge 通道。
✅ 3. App 平台打包说明
平台 | 说明 |
---|---|
Android | 使用 Android WebView + Java 实现容器,集成 H5+ SDK。\n打包工具:HBuilderX、CLI 构建 App 包(.apk) |
iOS | 使用 WKWebView + Objective-C 实现容器,集成 H5+ SDK。\n打包生成 .ipa 包,支持上架 App Store |
plus API | 统一封装摄像头、位置、文件系统、蓝牙、推送、支付等原生能力 |
Native 插件 | 可编写自定义原生插件,使用 Java(Android)或 Swift(iOS)开发,通过 JSBridge 调用 |
✅ 4. uni-app 的 App 通信示意图:
[ WebView 页面(Vue) ]
↓ JS 调用
[ plus.xxx API ]
↓
[ JSBridge 通道 ]
↓
[ 原生模块(如 Camera、Push、BLE) ]
↑
结果回调通过 JSBridge → JS
🧠 补充说明
项目 | uni-app App 平台表现 |
---|---|
性能 | 基于 WebView,复杂场景性能略逊于原生,但普通业务流畅运行无碍 |
原生扩展 | 支持自定义 Native 插件 + 云插件市场 |
通信机制 | 类似于 React Native 的 bridge,不过由 DCloud 完全封装,对开发者透明 |
安全 | plus API 具备权限校验机制,需在 manifest.json 配置权限声明 |
完整示例,展示在 uni-app 中的 App 端如何通过 JS 与 Native 插件(Java/Android 或 Swift/iOS)进行通信,包括:
- 前端 JS 如何调用原生方法;
- Android 原生插件如何实现;
- iOS 原生插件如何实现;
- 插件注册与 manifest 配置说明。
✅ 一、前端 JS 调用 Native 插件示例
// 调用自定义插件 myPlugin.hello
uni.callNativePlugin('myPlugin', 'hello', { name: 'IT iPower' }, res => {
console.log('原生返回结果:', res)
})
✅ 也可以使用 uniModules 提供的 Promise 封装方式(推荐):
import MyPlugin from '@/uni_modules/myPlugin/js_sdk/main.js'
MyPlugin.hello({ name: 'IT iPower' }).then(res => {
console.log('调用成功', res)
})
✅ 二、Android 插件实现(Java)
📄 1. 创建插件类:MyPlugin.java
package io.dcloud.uniapp.plugins;
import android.content.Context;
import android.widget.Toast;
import org.json.JSONObject;
import io.dcloud.feature.uniapp.common.UniModule;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
public class MyPlugin extends UniModule {
@UniJSMethod(uiThread = true)
public void hello(JSONObject options) {
String name = options.optString("name", "世界");
Toast.makeText(mUniSDKInstance.getContext(), "你好," + name, Toast.LENGTH_SHORT).show();
// 向 JS 回传值(如有回调)
JSONObject result = new JSONObject();
try {
result.put("msg", "来自 Android 原生的问候");
} catch (Exception e) {}
this.invokeCallback(options, result);
}
}
📌 说明:使用
@UniJSMethod
注解的方法可在 JS 中被调用。
📄 2. 插件注册(AndroidManifest.xml
)
<service android:name="io.dcloud.uniapp.plugins.MyPlugin" />
或者在 manifest.json
的 app-plus.modules
中声明:
"app-plus": {
"modules": {
"myPlugin": "io.dcloud.uniapp.plugins.MyPlugin"
}
}
✅ 三、iOS 插件实现(Swift)
📄 1. 创建插件类:MyPlugin.swift
import Foundation
import UIKit
@objc(MyPlugin)
class MyPlugin: NSObject {
@objc func hello(_ options: NSDictionary, callback: @escaping FlutterResult) {
let name = options["name"] as? String ?? "世界"
DispatchQueue.main.async {
let alert = UIAlertController(title: "Hello", message: "你好,\(name)", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true)
}
let result: [String: Any] = ["msg": "来自 iOS 原生的问候"]
callback(result)
}
}
📄 2. 插件注册
在 manifest.json
中配置模块映射:
"app-plus": {
"modules": {
"myPlugin": "MyPlugin"
}
}
✅ 四、文件结构建议(uni_modules)
uni_modules/
└── myPlugin/
├── js_sdk/
│ └── main.js // JS SDK 封装调用
├── android/
│ └── MyPlugin.java
├── ios/
│ └── MyPlugin.swift
└── manifest.json // 插件声明
📄 main.js
示例
function hello(data = {}) {
return new Promise((resolve, reject) => {
uni.callNativePlugin('myPlugin', 'hello', data, res => {
resolve(res)
})
})
}
export default {
hello
}
✅ 五、注意事项
项目 | 说明 |
---|---|
HBuilderX 调试 | 支持真机调试原生插件,使用“运行到手机” |
自定义插件封装建议 | 使用 uni_modules 统一结构 |
插件通信安全注意 | 参数校验、平台判断、异常处理 |
插件分发 | 可上传到 DCloud 插件市场 |