一、方案概述
在uni-app项目开发中,WebView组件常用于加载H5页面,实现混合开发模式。原生App(安卓、iOS)与WebView内H5页面的数据交互是混合开发的核心难点,本文系统性梳理App主动向H5传值、H5主动向App传值两种通信方向,详解 plus.webview.evalJS、postMessage 两种核心通信API,结合安卓录音文件回传、tempFilePath文件路径规则、AI语音识别实战场景,提供可直接落地的完整通信方案,同时补充兼容性适配、异常处理等开发注意事项。
二、通信基础概念与核心API说明
2.1 通信方向划分
• App → H5:原生端(安卓/iOS)主动向WebView内的H5页面发送数据,适用于App推送状态、设备信息、权限参数等场景。 • H5 → App:H5页面主动向原生App发送指令、业务数据,适用于H5触发原生功能(录音、拍照、支付)、页面状态同步等场景。
2.2 核心API简介
2.2.1 plus.webview.evalJS
该API为原生调用H5 JS方法的核心接口,支持App端直接执行H5页面内定义的JS函数,实现主动向H5推送数据,同步执行、响应速度快,适合高频、简单的数据传输。仅支持uni-app打包后的原生环境,H5浏览器环境无法使用。
2.2.2 postMessage
双向通用通信API,分为原生端postMessage和H5端postMessage,采用异步消息推送机制,支持复杂对象数据传输,可跨页面通信。适合非实时、大数据量、复杂结构的数据交互,是通用性最强的通信方式。
三、App → H5 通信实现方案
App向H5传值主流实现方式为 plus.webview.evalJS,原理是原生WebView实例获取H5全局JS方法,主动注入参数执行函数,完成数据推送。
3.1 前置准备
1. H5页面提前挂载全局接收方法,绑定至window对象,供原生调用,示例: window.receiveDataFromApp;2. uni-app端获取WebView实例,通过plus.webview.create创建页面或获取当前WebView对象; 3. 确保通信时机:需等待H5页面DOM加载完成后执行evalJS,避免方法未挂载导致调用失败。
3.2 完整代码实现
3.2.1 H5端代码(接收App数据)
// H5页面全局挂载接收方法,固定方法名供原生调用
window.receiveDataFromApp = function(params) {
// params:原生App传递的参数,支持字符串、对象、数组
console.log("App传递至H5的数据:", params);
// 业务逻辑处理:更新页面数据、修改页面状态、弹窗提示等
if(params.code === 200) {
// 处理正常业务数据
} else {
// 处理异常回调
}
}
3.2.2 uni-app原生端代码(推送数据至H5)
// 获取WebView实例
let webView = plus.webview.getWebviewById("h5-page");
// 等待页面加载完成,避免执行时机过早
webView.addEventListener("loaded", function() {
// 调用H5全局方法receiveDataFromApp,传递自定义参数
webView.evalJS(`
window.receiveDataFromApp({
code: 200,
msg: "原生推送数据成功",
data: {
device: "android",
version: "1.0.0"
}
})
`);
})
3.3 方案优缺点
• 优点:同步调用、响应延迟低、代码简洁、无额外事件监听; • 缺点:依赖全局JS方法挂载、复杂嵌套数据需手动序列化、跨域隔离严格。
四、H5 → App 通信实现方案
H5向原生App传值优先使用 postMessage,该方式无需提前挂载全局方法,通过消息队列异步推送数据,原生端监听message事件即可接收,适配复杂业务场景。
4.1 通信流程
H5触发postMessage发送消息 => 原生WebView监听message事件 => 原生解析数据执行业务逻辑 => 原生可通过evalJS回调结果至H5。
4.2 完整代码实现
4.2.1 H5端代码(发送数据至App)
// H5主动向原生App发送数据
function sendDataToApp() {
// postMessage支持对象、数组、字符串等格式数据
window.plus.webview.currentWebview().postMessage({
type: "h5-to-app",
operate: "startRecord",
content: "H5触发原生录音功能",
time: new Date().getTime()
})
}
4.2.2 uni-app原生端代码(监听接收H5数据)
let webView = plus.webview.getWebviewById("h5-page");
// 监听H5发送的message消息
webView.addEventListener("message", function(event) {
// event.data为H5传递的原始数据
let h5Data = event.data;
console.log("H5传递至App的数据:", h5Data);
// 根据type区分业务逻辑
switch(h5Data.operate) {
case "startRecord":
// 触发原生录音逻辑
startAndroidRecord();
break;
case "stopRecord":
// 停止录音
stopAndroidRecord();
break;
default:
break;
}
})
4.3 postMessage补充说明
1. 数据传输限制:不支持函数、DOM节点等特殊类型数据,传输前需过滤特殊格式; 2. 执行环境:仅plus环境可用,需判断 window.plus是否存在,避免浏览器环境报错;3. 回调方式:原生处理完成后,通过evalJS调用H5回调函数返回执行结果。
五、安卓录音回传实战(核心业务场景)
录音是混合开发高频场景,本文基于上述双向通信方案,实现H5触发原生录音、安卓原生录音、音频文件回传H5的完整流程,同时解析tempFilePath临时文件路径规则。
5.1 业务流程梳理
1. H5通过postMessage向App发送录音指令; 2. 安卓原生调用系统录音API,生成音频临时文件; 3. 原生获取音频tempFilePath临时路径; 4. 通过evalJS将文件路径、音频时长等数据回传给H5; 5. H5基于路径实现音频预览、上传、AI语音识别。
5.2 安卓原生录音代码实现
// 原生录音方法
function startAndroidRecord() {
// 申请录音权限
plus.android.requestPermissions(["android.permission.RECORD_AUDIO"], function(res) {
if(res.granted.length > 0) {
// 创建录音实例
let audioRecorder = plus.audio.createRecorder();
audioRecorder.start();
// 录音结束回调
audioRecorder.onstopped = function(path) {
// path为音频临时文件路径 tempFilePath
let tempFilePath = path;
// 将音频路径回传给H5
webView.evalJS(`
window.receiveDataFromApp({
code: 200,
type: "record-end",
filePath: "${tempFilePath}",
duration: ${audioRecorder.getDuration()}
})
`);
}
} else {
// 权限拒绝回调
webView.evalJS(`window.receiveDataFromApp({code: 403, msg: "录音权限拒绝"})`);
}
})
}
5.3 tempFilePath路径详解
5.3.1 路径定义
tempFilePath是uni-app原生生成的临时文件路径,属于应用私有目录,仅当前App可访问,无需手动申请文件读写权限,录音、拍照、截图生成的文件均默认存储至该目录。
5.3.2 安卓路径格式
// 安卓临时文件路径示例
/_doc/uniapp_temp/record/20260516/record_123456.amr
5.3.3 路径使用注意事项
• 生命周期:临时文件在App重启后可能被系统清理,重要音频需手动保存至持久目录; • H5访问权限:WebView默认允许访问应用私有临时路径,无需配置白名单; • 格式转换:安卓原生录音默认生成amr格式,H5播放器兼容性较差,建议转码为mp3格式。
六、AI语音识别集成方案
基于安卓录音回传的音频临时路径,结合第三方AI语音识别接口,实现音频转文字功能,适配H5+原生混合开发场景,提供两种落地方式。
6.1 方案一:原生解析+AI识别(推荐)
6.1.1 流程
安卓录音生成tempFilePath => 原生读取音频文件 => 调用AI语音识别SDK => 识别完成通过evalJS回传文本至H5。
6.1.2 核心代码片段
// 录音结束后执行AI识别
audioRecorder.onstopped = function(path) {
// 调用原生集成的AI语音识别接口
aiVoiceRecognition(path).then(res => {
// 识别结果回传给H5
webView.evalJS(`
window.receiveDataFromApp({
code: 200,
type: "ai-text",
filePath: "${path}",
text: "${res.text}",
confidence: ${res.confidence}
})
`);
})
}
6.2 方案二:H5解析+接口识别
1. 原生将tempFilePath传递至H5; 2. H5通过plus.io读取临时音频文件,转换为base64格式; 3. 调用云端AI语音识别API,上传base64音频数据; 4. 接收识别文本,完成业务渲染。
6.3 AI识别优化注意事项
• 音频压缩:录音文件过大将导致识别延迟,安卓端需配置音频采样率、比特率,压缩文件体积; • 异常处理:增加音频损坏、网络超时、识别失败的异常回调,兼容低版本安卓机型; • 权限配置:AI识别需网络权限,打包时需在manifest.json配置网络访问权限。
七、两种通信方式对比与选型标准
八、常见问题与兼容解决方案
8.1 方法调用失败(找不到H5全局方法)
问题原因:evalJS执行时机早于H5页面加载完成;解决方案:绑定WebView的loaded监听事件,页面加载完成后再执行通信方法。
8.2 安卓tempFilePath路径无法访问
问题原因:应用后台重启、临时文件被清理;解决方案:重要音频文件通过plus.io.moveTo方法迁移至持久目录。
8.3 postMessage数据丢失
问题原因:传输数据包含特殊格式、循环引用;解决方案:传输前使用JSON序列化数据,过滤函数、DOM节点。
8.4 低版本安卓录音兼容性问题
问题原因:安卓6.0以下无动态权限;解决方案:manifest.json配置最低兼容版本,静态声明录音权限。
九、总结
本文完整实现uni-app WebView与原生App双向通信方案,明确 evalJS用于App主动推送数据、postMessage用于H5主动触发原生功能 的核心选型逻辑。结合安卓录音场景,详解tempFilePath临时文件路径规则,搭配AI语音识别完成业务闭环。该方案适配绝大多数混合开发场景,代码可直接复用,同时通过权限处理、时机优化、异常兼容,解决安卓机型适配、文件访问、数据传输等常见问题,是uni-app混合开发WebView通信的通用落地方案。

夜雨聆风