ArkWeb 手记 08|H5 权限弹窗:相机、定位授权接管

前面 01~07,我们把 ArkWeb 生命周期、JS 通信、静态资源、调试缓存、请求拦截、页面新开窗口、文件上传全部过了一遍。

这一期解决混合项目另一个高频难题:H5 页面请求相机、地理位置权限的时候。

在浏览器打开 H5,会直接弹出浏览器授权窗口;但放到 ArkWeb 里面,默认不会自动弹出权限申请,H5 直接拿不到设备能力,接口返回失败。

核心误区:ArkWeb 不会自动处理 H5 的权限申请。H5 发起权限请求后,会触发onPermissionRequest回调,必须在这里手动判断权限类型,调用鸿蒙原生权限申请,再把结果回传给 ArkWeb。

核心概念一句话讲清

onPermissionRequest 是 H5 申请设备权限的回调。H5 调用 navigator.geolocation、getUserMedia 这些 API 时触发。

我们在回调里拿到请求的权限类型,手动拉起鸿蒙系统权限弹窗;用户同意 / 拒绝后,把结果回传给 ArkWeb,H5 才能继续执行逻辑。

类比:H5 只是提交权限申请单,真正能不能拿到相机、定位,决定权在鸿蒙原生层。
前置条件:HarmonyOS7,DevEco Studio,沿用前面工程,需要在 module.json5 声明对应权限。

第一步:module.json5 权限声明

复制代码
"requestPermissions": [
  {
    "name": "ohos.permission.CAMERA",
    "reason": "H5网页调用相机",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "inuse"
    }
  },
  {
    "name": "ohos.permission.LOCATION",
    "reason": "H5网页获取地理位置",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "inuse"
    }
  }
]

第二步:ArkTS 完整实现代码

复制代码
import { ArkWeb, ArkWebController, WebPermissionRequest, WebPermissionType } from '@kit.ArkWeb';
import { permissionManager } from '@kit.AbilityKit';

@Entry
@Component
struct WebPermissionDemo {
  controller: ArkWebController = new ArkWebController();

  aboutToAppear() {
    this.controller.javascriptEnabled = true;
    // 接管H5的权限申请
    this.controller.onPermissionRequest = async (req: WebPermissionRequest) => {
      // 遍历H5申请的权限类型
      for (const permType of req.permissionTypes) {
        if (permType === WebPermissionType.CAMERA) {
          // 申请相机原生权限
          const result = await permissionManager.requestPermissions("EntryAbility", ["ohos.permission.CAMERA"]);
          if (result.grantResults[0] === 0) {
            // 用户同意,授予权限
            req.grant(permType);
          } else {
            // 用户拒绝,拒绝授权
            req.deny(permType);
          }
        } else if (permType === WebPermissionType.GEOLOCATION) {
          // 申请定位原生权限
          const result = await permissionManager.requestPermissions("EntryAbility", ["ohos.permission.LOCATION"]);
          if (result.grantResults[0] === 0) {
            req.grant(permType);
          } else {
            req.deny(permType);
          }
        }
      }
    }
  }

  build() {
    Column() {
      ArkWeb({
        src: $rawfile("index.html"),
        controller: this.controller
      })
      .width('100%')
      .layoutWeight(1)
    }
  }
}

配套 H5 index.html 测试代码

复制代码
<button onclick="getLocation()">获取定位</button>
<button onclick="openCamera()">调用相机</button>
<script>
// 获取定位
function getLocation(){
  navigator.geolocation.getCurrentPosition((pos)=>{
    alert(`经度:${pos.coords.longitude},纬度:${pos.coords.latitude}`)
  },err=>{
    alert("定位失败:"+err.message)
  })
}
// 调用相机
async function openCamera(){
  try{
    const stream = await navigator.mediaDevices.getUserMedia({video:true})
    alert("相机打开成功")
  }catch(e){
    alert("相机授权失败:"+e.message)
  }
}
</script>

关键语句拆解:

  1. onPermissionRequest接收 WebPermissionRequest 对象,用grant()授予权限、deny()拒绝权限。
  2. WebPermissionType 枚举区分权限:CAMERA 相机、GEOLOCATION 定位,还有 MICROPHONE 麦克风。
  3. 必须先在 module.json5 静态声明权限,否则requestPermissions直接申请失败。

第三步:权限状态预判断(优化用户体验)

每次 H5 触发申请都弹窗,体验不好。可以先检查是否已经授权,避免重复弹窗:

复制代码
// 检查权限是否已授权
const status = await permissionManager.checkPermission("ohos.permission.CAMERA");
if(status === permissionManager.GRANTED){
  req.grant(WebPermissionType.CAMERA);
}

高频踩坑清单(重点)

  1. ❌ H5 调用定位 / 相机,没有任何授权弹窗,直接报错
    ✅ 没有实现onPermissionRequest回调,ArkWeb 不会处理 H5 权限请求。
  2. ❌ 代码写了 grant (),H5 依旧拿不到权限
    ✅ module.json5 没有声明对应权限;或者真机没有弹窗手动允许,模拟器部分权限存在限制。
  3. ❌ 一次性申请多个权限,只处理了其中一个
    ✅ 权限类型放在 permissionTypes 数组,要用循环逐个判断、逐个 grant/deny,不能只处理第一项。
  4. ❌ 页面销毁之后,还保留权限回调引用,引发内存泄漏
    ✅ 页面退出时,不要保留 controller 的 onPermissionRequest 引用,简单置空即可。

小扩展:全局拒绝某些权限(安全管控)

业务需求,直接禁止 H5 使用相机,不需要弹窗,直接 deny

复制代码
this.controller.onPermissionRequest = async (req: WebPermissionRequest) => {
  for (const permType of req.permissionTypes) {
    // 直接拒绝相机
    if (permType === WebPermissionType.CAMERA) {
      req.deny(permType);
    }
  }
}
相关推荐
特立独行的猫A1 小时前
用仓颉语言写一个漂亮的桌面音乐播放器:cj-tauri 实战
harmonyos
m0_738185821 小时前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙
熊猫钓鱼>_>2 小时前
开源鸿蒙平台 KMP 三方库 KStore 适配全流程:从 ohosArm64 target 到真机文件持久化验证
人工智能·华为·开源·ai编程·harmonyos·openharmony·kmp
CV工程师丁Sir2 小时前
ArkWeb 手记 07|H5 文件上传:对接鸿蒙文件选择器
华为·harmonyos
Geek_Vison2 小时前
政务APP新增鸿蒙客户端,如何复用已有的业务单元?
小程序·harmonyos·mpaas·政务·小程序容器
@#¥&~是乱码鱼啦3 小时前
ArkWeb开发手记05|SPA单页H5适配、自定义历史栈与全局状态同步
前端·harmonyos
xq952720 小时前
ArkTS Component Generator 插件横空出世
harmonyos
Fate_I_C21 小时前
Capacitor 插件鸿蒙化实战:@capacitor/device 从安装到模拟器验证全记录
华为·harmonyos