本文将分享如何在 uniapp 开发中申请相机和相册权限时,解决应用商店要求同步告知权限申请目的的问题,并兼容 Android 13。
背景
在某一次版本迭代中,上架华为应用商店审核不通过,原因是申请相机、相册权限时「未同步告知权限申请的使用目的」。
审核方给出的修改建议如下:
修改建议:APP在申请敏感权限时,应同步说明权限申请的使用目的,包括但不限于申请权限的名称、服务的具体功能、用途;告知方式不限于弹窗、蒙层、浮窗、或者自定义操作系统权限弹框等。请排查应用内所有权限申请行为,确保均符合要求。
特别提示:需在申请权限的同时/过程中同步告知目的。
在申请权限的同时给用户同步告知目的,建议申请目的与“权限弹窗”需同屏展示。
分析
简而言之,申请权限之前,需要同步显示“提示”,告知用户权限的使用目的,不能提前告知,也不能在申请权限之后再告知。
- 因为不能每次都显示申请目的,如何判断当前是否已经拥有权限?
- 在用户未对权限弹窗进行操作时,如何确保告知目的不会消失,并且与权限弹窗同屏显示?
难点:
- 判断权限是否已授权
- 权限申请流程
- 实现持久性弹窗
解决
由于主要针对安卓应用商店,这里只考虑安卓的情况,iOS部分较为简单。
回到难点上,
如何判断当前有无权限
在 uniapp 中可以使用 plus.navigator.checkPermission(permission)
API 检查运行环境的权限,入参 permission
是权限的名称。其中,相机、相册的权限名称分别为:
android.permission.CAMERA
android.permission.READ_EXTERNAL_STORAGE
该 API 返回一个字符串,表示权限的授权状态。authorized
代表已被用户授权使用此权限。其他返回值请查阅 此处。
因此,我们只需要判断返回的权限状态是否为 authorized
,如果是,则表示已有权限,无需继续申请;否则,需要申请对应权限。
申请权限
使用 plus.android.requestPermissions(Array[String] permissions, AndroidSuccessCallback successCb, AndroidErrorCallback errorCB)
API 可以向系统请求权限。其中,permissions
是申请的权限列表,successCb
是申请权限成功后的回调函数,errorCB
是失败回调函数(通常用于处理参数错误的情况)。
- 成功回调函数
successCb
包含三个参数:granted
- 已获取的权限列表(字符串数组);deniedPresent
- 被临时拒绝的权限列表(字符串数组);deniedAlways
- 被永久拒绝的权限列表(字符串数组)。
官方使用示例:
// 申请定位权限
function requestLocation(){
plus.android.requestPermissions(['android.permission.ACCESS_FINE_LOCATION'], function(e){
if(e.deniedAlways.length>0){
//权限被永久拒绝
// 弹出提示框解释为何需要定位权限,引导用户打开设置页面开启
console.log('Always Denied!!! '+e.deniedAlways.toString());
}
if(e.deniedPresent.length>0){
//权限被临时拒绝
// 弹出提示框解释为何需要定位权限,可再次调用plus.android.requestPermissions申请权限
console.log('Present Denied!!! '+e.deniedPresent.toString