搞定了 ArkWeb 基础页面搭建,把 Web 组件生命周期做了绑定,解决最头疼的内存泄漏问题。但很多同学照着代码跑通之后,马上遇到新麻烦:H5 页面调用摄像头直接拒绝、上传图片无响应;更换 H5 资源之后 APP 里面还是旧页面,缓存脏数据清不掉;部分内网域名直接拦截打不开。
这些问题大多不是代码逻辑 bug,而是 ArkWeb 的权限、网络访问策略和缓存机制没配置到位。很多新手会误以为只要申请INTERNET网络权限,所有网页就能随便跑。实际 HarmonyOS7 对 ArkWeb 做了严格的访问隔离,网页想调用设备能力、访问指定域名,都需要单独授权;浏览器缓存也需要手动管控,否则上线之后会埋下一堆隐性问题。
本篇手记,我们就把 ArkWeb 配套配置一次性讲透:网页设备权限申请、网络域名白名单配置、页面缓存策略管理,同时演示手动清理缓存、禁用缓存的实战代码。
前置阅读:掌握 ArkWeb 基础页面与生命周期管理 前置环境:DevEco Studio 白色皮肤,HarmonyOS7 SDK
一、先分清两个权限:系统权限 和 ArkWeb 网页权限
很多人在这里混淆,踩坑率极高。
- 应用系统权限:在
module.json5里面声明,是 APP 整体向操作系统申请权限,比如网络、相机、存储。没有这个声明,APP 根本没有调用硬件的资格。 - ArkWeb 网页权限:H5 页面在 Web 内核里发起权限请求(比如 H5 调用摄像头、麦克风、相册),需要我们在 ArkTS 代码中写回调,手动同意或者拒绝网页的请求。 就算你在 module.json5 声明了相机权限,如果 ArkWeb 没有配置权限回调,H5 发起摄像头调用时,依然会直接被拦截,H5 拿不到摄像头流。
类比理解:系统权限相当于小区给你办了门禁卡,允许你进入小区;ArkWeb 权限回调相当于家里的房门,H5 访客想进房间,你需要开门放行。门禁有了,房门不开,访客依旧进不来。
1.1 module.json5 基础权限配置
首先在 module.json5 中,除了 INTERNET,把 H5 常用能力对应的系统权限提前声明。
"requestPermissions": [ { "name": "ohos.permission.INTERNET" }, { "name": "ohos.permission.CAMERA" }, { "name": "ohos.permission.MICROPHONE" }, { "name": "ohos.permission.READ_MEDIA" } ]注意:
ohos.permission.READ_MEDIA用于 H5 选择相册图片。HarmonyOS7 不再推荐旧的 READ_EXTERNAL_STORAGE,媒体文件读取统一使用 READ_MEDIA。
1.2 ArkWeb 网页权限回调代码
Web 组件提供onPermissionRequest回调,专门拦截 H5 发起的权限申请,我们在这里做判断,决定允许或者拒绝。
Web({ src: "https://example.com", controller: this.webController }) .width('100%') .height('80%') .onPermissionRequest((permissionReq) => { console.info("H5发起权限请求,类型:", permissionReq.getPermissionType()) // 允许H5使用摄像头、麦克风 if(permissionReq.getPermissionType() === WebPermissionType.CAMERA || permissionReq.getPermissionType() === WebPermissionType.MICROPHONE){ permissionReq.grant(); }else{ permissionReq.deny(); } })grant():放行,允许 H5 使用该设备能力deny():拒绝本次权限申请
踩坑提醒:这个回调只处理 H5 网页发起的权限。原生页面弹窗申请权限,还是要用
requestPermissionFromUser,不要混在一起。
二、网络域名白名单:网络安全策略配置
HarmonyOS7 默认开启网络安全限制。如果访问 HTTP 非加密地址,或者访问未加入白名单的内网域名,网页直接拦截,报网络错误。很多人本地测试内网 H5,死活打不开网页,根源就是没有配置域名白名单。
网络安全配置写在module.json5的networkSecurity节点,支持配置:允许明文 HTTP 访问、域名白名单。
"networkSecurity": { "cleartextTraffic": { "allow": true }, "domainRules": [ { "domains": ["192.168.1.*", "localhost"], "cleartextTraffic": { "allow": true } }, { "domains": ["*.example.com"], "cleartextTraffic": { "allow": false } } ] }参数说明:
cleartextTraffic allow:true:允许 HTTP 明文请求;生产环境公网域名建议关闭,只给内网、本地调试开启。domainRules域名规则:支持通配符*.xxx.com,可以针对不同域名单独控制是否允许 HTTP。
重要提醒:上线正式包,公网业务域名不要开启 cleartextTraffic,尽量全部使用 HTTPS,避免通信内容被抓包篡改。内网调试环境才打开 HTTP 明文访问。
常见坑
配置完白名单之后,修改 module.json5,必须卸载模拟器 / 真机上旧应用,重新编译安装。缓存的应用配置不会自动更新,很多人改完配置直接热重载,结果一直不生效,白白浪费大量调试时间。
三、ArkWeb 页面缓存机制与管控
ArkWeb 内核自带缓存,会自动保存网页资源:JS、CSS、图片、HTML。好处是二次打开页面加载更快;坏处是发布 H5 新版本之后,用户 APP 依旧加载旧缓存页面,出现版本不一致、bug 无法修复,也就是大家常说的缓存脏数据。
我们有三种缓存控制方案:
- 全局关闭缓存(调试阶段常用)
- 加载页面时禁用本次请求缓存
- 代码主动清理全部 Web 缓存
3.1 全局缓存设置:WebController.setCacheMode
通过控制器设置缓存模式,支持 4 种模式:
- CacheMode.Default:默认,根据 http header 自动判断是否缓存(线上默认)
- CacheMode.None:不使用缓存,全部从网络拉取(调试首选)
- CacheMode.Online:优先网络,网络失败才读缓存
- CacheMode.Offline:优先本地缓存,离线模式
aboutToAppear() { // 调试环境,禁用缓存,每次都拉最新资源 this.webController.setCacheMode(CacheMode.None); }注意:setCacheMode 建议在页面初始化 aboutToAppear 调用,不要在页面加载中途修改,中途修改容易失效。
3.2 主动清除缓存代码
产品版本更新的时候,我们可以提供一个 “清除网页缓存” 按钮,一键清理 ArkWeb 内核缓存。
Button("清空Web缓存") .margin(10) .onClick(async ()=>{ await this.webController.clearCache(true); // true:同时清除cookie,false只清理资源缓存 console.info("ArkWeb缓存清理完成"); })clearCache(boolean includeCookie):参数 true,清理缓存同时删除网页 Cookie;false 只清理静态资源。
四、整合完整代码(权限回调 + 缓存控制 + 生命周期)
把《Web 组件 H5 加载与生命周期管理》的生命周期代码 + 权限回调 + 缓存设置整合在一起,完整可直接运行:
import { Web, WebController, WebLoadStatus, WebPermissionType, CacheMode } from '@kit.ArkWeb'; import { router } from '@ohos/router'; @Entry @Component struct ArkWebConfigPage { private webController: WebController = new WebController(); @State loadStatus: string = "待加载"; @State hasError: boolean = false; aboutToAppear() { console.info("aboutToAppear:页面准备渲染"); // 设置缓存模式,调试环境禁用缓存 this.webController.setCacheMode(CacheMode.None); } onPageShow() { console.info("onPageShow 页面前台"); this.webController.resume(); } onPageHide() { console.info("onPageHide 页面后台"); this.webController.pause(); } aboutToDisappear() { console.info("aboutToDisappear 页面销毁"); this.webController.destroy(); } build() { Column() { Text(`H5加载状态:${this.loadStatus}`) .fontSize(16) .margin({top:10}) Button("清空Web缓存") .margin(10) .onClick(async ()=>{ await this.webController.clearCache(true); }) if(this.hasError){ Column(){ Text("页面加载失败") .fontSize(20) .margin(10) Button("重新加载") .onClick(()=>{ this.hasError = false; this.webController.reload(); }) } } Web({ src: "https://example.com", controller: this.webController }) .width('100%') .height('70%') .onLoadStatusChange((status: WebLoadStatus) => { switch(status) { case WebLoadStatus.StartLoading: this.loadStatus = "开始加载H5页面"; this.hasError = false; break; case WebLoadStatus.FinishLoading: this.loadStatus = "页面加载完成"; this.hasError = false; break; case WebLoadStatus.ErrorLoading: this.loadStatus = "页面加载失败,请检查网络/域名白名单"; this.hasError = true; break; } }) .onErrorReceive((err)=>{ console.error("H5加载异常", JSON.stringify(err)); this.hasError = true; }) .onPermissionRequest((permissionReq) => { console.info("H5权限请求", permissionReq.getPermissionType()) // 放行摄像头、麦克风 if(permissionReq.getPermissionType() === WebPermissionType.CAMERA || permissionReq.getPermissionType() === WebPermissionType.MICROPHONE){ permissionReq.grant(); }else{ permissionReq.deny(); } }) } .width('100%') .height('100%') } }五、实战测试,验证配置效果
测试 1:H5 相机权限
写一个简单 H5 页面,调用 navigator.mediaDevices 获取摄像头。
- module.json5 声明 CAMERA 权限
- ArkWeb 增加 onPermissionRequest 放行相机权限
- 真机打开页面,H5 正常唤起摄像头;注释 grant 改为 deny,H5 获取媒体流直接报错。
注意:模拟器没有摄像头硬件,权限测试必须真机测试,模拟器只能做代码语法校验。
测试 2:内网域名访问
配置 networkSecurity 白名单,填写本地局域网 IP,开启 cleartextTraffic。
- 配置正确:内网 H5 页面正常打开;
- 不配置白名单:页面直接加载失败,报网络拦截。
测试 3:缓存验证
- CacheMode.Default,打开页面,修改服务端 H5 页面内容,再次访问,展示旧页面(缓存生效)
- 切换 CacheMode.None,刷新页面,直接拿到最新 H5 内容
- 点击清空缓存按钮,清理所有资源与 Cookie
这里有个坑:clearCache只能清理 ArkWeb 内核的缓存。H5 前端代码里 localStorage、sessionStorage 不属于这个缓存,不会被 clearCache 清除。如果 H5 业务数据存在 localStorage,要让前端 H5 自己清理,原生这边无法直接清除。很多同学误以为 clearCache 能清理 H5 本地存储,结果上线踩坑。
六、本篇小结
本篇我们搞定 ArkWeb 配套的三大核心配置:网页设备权限、网络域名白名单、页面缓存管理。很多 ArkWeb 线上问题,根源都在这些配置项,不是业务代码问题。
知识点回顾
- 区分 APP 系统权限(module.json5)和 ArkWeb 网页权限(onPermissionRequest 回调),二者缺一不可;
- HarmonyOS7 网络安全策略默认拦截未配置的内网域名、HTTP 明文请求,内网调试需要配置 networkSecurity 域名白名单;
- CacheMode 四种缓存模式,调试优先 CacheMode.None,生产环境默认 Default;
- webController.clearCache () 清理 Web 资源缓存 + Cookie,但无法清除 H5 localStorage/sessionStorage;
- 修改 module.json5 配置之后,需要卸载重装应用,热重载不会更新安全配置。
实践指南:
- 搭建本地简易 HTTP 服务,在内网放一个 H5 页面,配置域名白名单,在 ArkWeb 访问内网页面;
- 写 H5 的摄像头调用页面,真机测试 onPermissionRequest 放行 / 拒绝两种情况的效果;
- 分别切换 CacheMode.Default 和 CacheMode.None,观察页面资源缓存差异。