鸿蒙 ASCF has.authorize 授权配置与拒绝处理
在鸿蒙元服务开发中,ASCF 把权限申请收口到一个方法:has.authorize。无论是访问位置、通讯录、日历等用户数据,还是调用相机、麦克风、蓝牙等系统能力,都要先拿到用户授权。它看起来简单,但 scope 怎么配、module.json5 怎么声明、用户拒绝后怎么办,实际开发中很容易踩坑。下面按基本调用、权限声明、scope 对照、典型场景和排障点梳理。一、has.authorize 基本调用
has.authorize 只有一个方法入口,scope 必填,用于指定申请的权限类型。如果用户之前已经同意过授权,不会再弹窗,直接走 success。
has.authorize({
scope: 'scope.userLocation',
success: () => {
console.info('用户已授权');
},
fail: (err) => {
console.error('授权失败:', err);
}
});
二、权限配置三步走
第一步,在 module.json5 的 requestPermissions 中声明系统权限,例如 CAMERA、MICROPHONE、LOCATION、APPROXIMATELY_LOCATION。不声明就调用 authorize,会直接走 fail。
第二步,在代码里通过 has.authorize 请求授权:
has.authorize({
scope: 'scope.camera',
success: () => { /* 权限已拿到 */ },
fail: (err) => { /* 被拒绝或未声明 */ }
});
第三步,处理失败情况。用户可能拒绝授权,拒绝后再次调用 has.authorize,可能不再弹窗,直接走 fail。
三、scope 与系统权限对照
位置:scope.userLocation 对应精确定位,需要 LOCATION 和 APPROXIMATELY_LOCATION 两个权限;scope.userFuzzyLocation 对应模糊定位,只需要 APPROXIMATELY_LOCATION。
设备:scope.camera 用于相机;scope.record 用于录音,录像需要同时具备 camera 和 record 权限。
联系人:scope.contact。
日历:scope.calendar。
蓝牙:scope.bluetooth。
通知:scope.notification。
这里要注意,一个 scope 可能对应多个系统权限,漏声明一个都会失败。
四、先授权再调用是常见模式
几乎所有需要权限的 API,都要先 authorize 再调用。直接调用业务 API,没授权时可能直接失败;正确做法是先申请对应 scope,再在 success 回调里调用业务 API。项目里蓝牙、通讯录、日历、WiFi 都遵循这个顺序。
// 蓝牙
has.authorize({
scope: 'scope.bluetooth',
success: () => {
has.openBluetoothAdapter({ ... });
}
});
// 通讯录
has.authorize({
scope: 'scope.contact',
success: () => {
has.addPhoneContact({ ... });
}
});
// 日历
has.authorize({
scope: 'scope.calendar',
success: () => {
has.addPhoneCalendar({ ... });
}
});
// WiFi:获取列表需要定位权限
has.authorize({
scope: 'scope.userLocation',
success: () => {
has.getWifiList({ ... });
}
});
其中 WiFi 获取列表需要 scope.userLocation 权限,因为 WiFi 信息可用于定位,这一点比较反直觉。
五、用 Promise 封装授权
每次都写 success/fail 回调比较繁琐,可以封装成 Promise:
function authorize(scope) {
return new Promise((resolve, reject) => {
has.authorize({
scope: scope,
success: () => resolve(),
fail: (err) => reject(err)
});
});
}
async function getLocation() {
try {
await authorize('scope.userLocation');
const location = await new Promise((resolve, reject) => {
has.getLocation({
success: (res) => resolve(res),
fail: (err) => reject(err)
});
});
console.info('位置:', location);
} catch (err) {
console.error('获取位置失败:', err);
}
}
六、典型场景
场景一,一次性申请多个权限。某些功能需要多个权限,比如录像需要相机和麦克风:
async function startRecording() {
try {
await authorize('scope.camera');
await authorize('scope.record');
// 两个权限都拿到了
const ctx = has.createCameraContext();
ctx.startRecord({ ... });
} catch (err) {
has.showToast({ title: '需要相机和麦克风权限' });
}
}
场景二,权限拒绝后的引导。用户拒绝后再次调用 authorize 可能不再弹窗,可以提示用户去设置页手动开启:
has.authorize({
scope: 'scope.userLocation',
fail: (err) => {
has.showModal({
title: '需要定位权限',
content: '请在设置中开启定位权限',
confirmText: '去设置',
success: (res) => {
if (res.confirm) {
has.openSetting({
success: (settingRes) => {
// 检查用户是否在设置里开启了权限
console.info('设置结果:', settingRes);
}
});
}
}
});
}
});
has.openSetting 可以打开元服务的设置页面,用户可以在那里手动开启权限。
场景三,按需申请。不要一进应用就申请所有权限,用户会烦。应该在真正需要的时候再申请:
Page({
// 用户点击扫一扫按钮时才申请相机权限
onScanTap() {
has.authorize({
scope: 'scope.camera',
success: () => {
has.scanCode({
success: (res) => {
console.info('扫码结果:', res.result);
}
});
},
fail: () => {
has.showToast({ title: '需要相机权限才能扫码' });
}
});
},
// 用户点击添加联系人时才申请通讯录权限
onAddContact() {
has.authorize({
scope: 'scope.contact',
success: () => {
has.addPhoneContact({ ... });
}
});
}
});
七、常见踩坑与排障
1. module.json5 没声明权限。这是最常见错误,scope 对应的系统权限必须在 requestPermissions 里声明,否则直接 fail。比如 scope.userLocation 必须声明 LOCATION 和 APPROXIMATELY_LOCATION 两个权限。
2. scope 和系统权限的对应关系不是一一对应。一个 scope 可能对应多个系统权限,漏一个都会失败。
3. 用户拒绝后不再弹窗。再次调用 has.authorize 可能直接走 fail,需要用 has.openSetting 引导用户去设置里手动开启。
4. WiFi 需要定位权限。获取 WiFi 列表需要 scope.userLocation 权限。
5. 后台定位需要额外配置。scope.userFuzzyLocation 用于前台定位;如果需要后台持续定位,除了权限,还需要在 module.json5 里配置 backgroundModes: ['location']。
6. 单次授权。HarmonyOS 支持单次授权,用户选择仅本次允许后,下次使用时需要重新申请,不要假设之前授权过就一直有效。
7. 权限分类。ASCF 的 scope 对应的都是敏感权限,所以都会弹窗。
八、小结
ASCF 授权 API 只有 has.authorize 一个方法,但它是所有需要权限 API 的前置步骤。排查时先记住三步:module.json5 声明权限、代码里 authorize、处理失败情况。用户拒绝后用 openSetting 引导,按需申请,不要一次性全申请。遇到 fail,先检查 module.json5 有没有声明对应的系统权限,再检查 scope 是否正确。
Re: 鸿蒙 ASCF has.authorize 授权配置与拒绝处理
这篇梳理挺实用的,尤其是把 has.authorize 的调用、module.json5 声明、scope 对照和先授权再调用串起来了。实际开发里最容易栽的就是:只盯着 scope,忘了 requestPermissions 里对应系统权限也要声明;还有 userLocation 要同时有 LOCATION 和 APPROXIMATELY_LOCATION,WiFi 获取列表居然也要定位权限,确实反直觉。拒绝后可能不再弹窗、需要引导去 openSetting 这一段也很关键,不然用户点了拒绝功能就卡死。Promise 封装那段可以直接抄进项目里,比每次写 success/fail 清爽。另外文末好像停在“ha”,是不是还没发完?如果还有排障点或拒绝处理的补充,可以继续贴出来。Re: 鸿蒙 ASCF has.authorize 授权配置与拒绝处理
这篇整理很实用,尤其是把 scope 和系统权限的对应关系单独拎出来讲。我之前就踩过只调 has.authorize 但没在 module.json5 里声明权限的坑,结果直接走 fail,排查起来挺费时间。你提到一个 scope 可能对应多个系统权限也很关键,像定位要 LOCATION 和 APPROXIMATELY_LOCATION,录像要 camera 和 record,漏一个都不行。 拒绝后不再弹窗、需要引导用户去设置页开启权限这部分也很贴合实际,不然用户会以为点了没反应。用 Promise 封装 authorize 那段思路很清楚,后面先授权再调用业务 API 的顺序会更好维护。 想确认一个细节:在 openSetting 里开启权限后,是回到页面重新调一次 authorize 再执行业务,还是可以直接继续调用?帖子正文这里好像没展开,如果后面能补充一下就更好了。Re: 鸿蒙 ASCF has.authorize 授权配置与拒绝处理
感谢分享,这篇把 has.authorize 的调用、声明和拒绝处理串起来了,很实用。几个点印象比较深:scope 必填且已授权不弹窗;module.json5 不声明直接 fail;一个 scope 可能对应多个系统权限,漏一个都不行;WiFi 列表要 scope.userLocation 确实反直觉。Promise 封装和拒绝后 showModal 引导 openSetting 这两段也很适合直接套到项目里。想请教一下,像录像这种要 camera 和 record 两个权限的场景,如果第一个授权成功、第二个被拒,业务侧一般怎么记录状态比较稳妥?还有用户拒绝后再次 authorize 不弹窗时,是不是基本只能靠 openSetting 让用户手动开?整体思路很清晰,收藏了。
页:
[1]