更新记录
2.0.0(2026-11-06)
封装了IOS原生webview,重复弹出麦克风和相机权限问题
平台兼容性
uni-app(4.0)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | - | - | - | √ | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.0)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | - | √ | - | - |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| × | × | × | √ |
hy-media-auto-grant
iOS WKWebView 网页层摄像头/麦克风(getUserMedia)自动授权插件。
1. 介绍
解决什么问题
uni-app 的 <web-view> 加载的 H5 页面在 iOS 上调用 getUserMedia(如 TRTC Web SDK 视频问诊)时,WKWebView 会每次弹出网页层授权弹窗——即使 App 系统权限已经授权。原因:
- App 系统权限(TCC)与 WKWebView 网页层权限是两层独立体系;
- WKWebView 不持久化网页授权,且 uni-app 的 web-view 子 webview 没有设置
uiDelegate,WebKit 因此走默认弹窗路径。
本插件扫描窗口树中的 WKWebView,将其 uiDelegate 替换为自带的媒体授权代理。此后:
- 系统层摄像头 + 麦克风均已授权 → 网页层授权自动 grant,不再弹窗;
- 任一系统权限未授权 →
decisionHandler(.prompt),弹出与原生默认一致的授权窗(不绕过、不伪造系统授权)。
影响范围(重要)
| 维度 | 范围 |
|---|---|
| 平台 | 仅 iOS App(iOS 15+)。Android 为空实现(no-op);H5、小程序端不涉及 |
| Webview | 仅接管 URL 以 urlPrefix 开头的 H5 子 webview;uni-app 自身页面 webview(file://...__uniappview.html)及其他域名 webview 不受影响 |
| 权限类型 | 仅网页层摄像头/麦克风授权(requestMediaCapturePermissionForOrigin 回调)。地理定位、通知等其他 H5 授权不受影响 |
| 决策逻辑 | 双系统权限 authorized → 自动 grant;否则 .prompt(等同默认弹窗) |
| 附带行为 | alert() 不再弹、confirm() 返回 false、prompt() 返回 null(与之前 nil-delegate 默认行为一致) |
前提条件
壳工程进入 webview 前申请 App 级系统权限的逻辑必须保留——本插件的 auto-grant 以系统权限已授权为前提。
2. 安装方法
方式一:本地 uni_modules(当前项目已内置)
插件位于 uni_modules/hy-media-auto-grant/,HBuilderX 导入工程后即可使用,无需额外安装。
方式二:复制到其他工程
将整个 uni_modules/hy-media-auto-grant/ 目录复制到目标工程的 uni_modules/ 下。
关键要求
- iOS 最低版本 15.0(
requestMediaCapturePermissionForOrigin为 iOS 15+ API),已在插件package.json声明app-ios.minVersion: 15.0; - manifest.json 中 iOS webview 内核必须是 WKWebview(
"app-plus" → "distributed" → "ios" → "WKWebview": true或 UIWebview 关闭); - 修改插件内任何 UTS/Swift 源码后,必须重新打自定义基座(同时在插件
package.json中递增version强制云编译);纯 JS 调用侧改动热推即可。
3. 代码演示
API 签名
// uni_modules/hy-media-auto-grant
export function installHook(
cameraAuthorized: boolean, // 系统层摄像头是否已授权
microphoneAuthorized: boolean, // 系统层麦克风是否已授权
urlPrefix: string // 只接管 URL 以此开头的 webview,传空串时不接管任何 webview
): string
// 返回 JSON 字符串,需 JSON.parse:
// { "installed": boolean, "webviewCount": number, "totalWebviews": number, "urls": string[] }
完整调用示例(web-view 宿主页面)
<template>
<view>
<web-view :src="baseUrl" @message="onMessage"></web-view>
</view>
</template>
<script>
// #ifdef APP-PLUS
import { installHook } from '@/uni_modules/hy-media-auto-grant';
// #endif
export default {
data() {
return {
baseUrl: 'https://your-h5-domain.com'
};
},
onReady() {
// #ifdef APP-PLUS
this.installMediaAutoGrant(0);
// #endif
},
methods: {
installMediaAutoGrant(retry) {
// #ifdef APP-PLUS
try {
// 1. 查询 App 系统权限状态
const setting = uni.getAppAuthorizeSetting();
const cameraOk = setting.cameraAuthorized === 'authorized';
const micOk = setting.microphoneAuthorized === 'authorized';
// 2. 提取 baseUrl 的协议+域名+端口作为前缀(域名后可能直接跟 ?query,注意排除)
const m = /^https?:\/\/[^\/?]+/.exec(this.baseUrl || '');
const urlPrefix = m ? m[0] : '';
// 3. 安装代理(幂等,已接管的 webview 自动跳过)
const res = JSON.parse(installHook(cameraOk, micOk, urlPrefix));
console.log('install:', JSON.stringify(res));
// res 示例: { "installed": true, "webviewCount": 1, "totalWebviews": 1, "urls": ["https://your-h5-domain.com/xxx"] }
// 4. web-view 子 webview 可能晚于 onReady 创建,定时重试兜底
if (retry < 9) {
setTimeout(() => this.installMediaAutoGrant(retry + 1), 1000);
}
} catch (e) {
console.error('install error', e);
}
// #endif
},
onMessage(e) {
const data = e.detail.data[0];
// H5 跳转视频页前通知 App 端,立即再 install 一次(单次,不重试)
if (data.type === 'watchRouterH5Change') {
// #ifdef APP-PLUS
this.installMediaAutoGrant(9);
// #endif
}
}
}
};
</script>
H5 侧配合(可选但推荐)
H5 在跳转需要摄像头/麦克风的页面前,通过 uni.postMessage 通知宿主:
// kernel-app H5 内
uni.webView.postMessage({
data: { type: 'watchRouterH5Change' }
});
返回值说明
| 字段 | 类型 | 说明 |
|---|---|---|
installed |
boolean | 是否执行了安装(urlPrefix 为空串时返回 false) |
webviewCount |
number | 本次新接管(安装代理)的 webview 数量 |
totalWebviews |
number | 扫描到的全部 WKWebView 数量 |
urls |
string[] | 扫描到的各 webview 当前 URL,用于排查 |
排查要点
webviewCount: 0且totalWebviews > 0:子 webview 的 URL 不匹配urlPrefix,检查 baseUrl 配置与正则提取结果;totalWebviews: 0:web-view 子 webview 尚未创建,靠重试链覆盖;- 接管后 H5 的
alert()不再弹出,需提示的页面建议改用 Toast。

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 15
赞赏 0
下载 12747875
赞赏 1959
赞赏
京公网安备:11010802035340号