向用户申请授权
说明:
当前为Beta阶段。
当应用需要访问用户的隐私信息或使用系统能力时,例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等,应该向用户请求授权,这部分权限是user_grant权限。
当应用申请user_grant权限时,需要完成以下步骤:
-
在配置文件中,声明应用需要请求的权限。
-
将应用中需要申请权限的目标对象与对应目标权限进行关联,让用户明确地知道,哪些操作需要用户向应用授予指定的权限。
以上两步请参见章节声明权限完成。
-
运行应用时,在用户触发访问操作目标对象时应该调用接口,精准触发动态授权弹框。该接口的内部会检查当前用户是否已经授权应用所需的权限,如果当前用户尚未授予应用所需的权限,该接口会拉起动态授权弹框,向用户请求授权。
-
检查用户的授权结果,确认用户已授权才可以进行下一步操作。
本章节会介绍如何完成步骤3和4。
约束与限制
-
user_grant权限授权要基于用户可知可控的原则,需要应用在运行时主动调用系统动态申请权限的接口,系统弹框由用户授权,用户结合应用运行场景的上下文,识别出应用申请相应敏感权限的合理性,从而做出正确的选择。
-
系统不鼓励频繁弹窗打扰用户,如果用户拒绝授权,将无法再次拉起弹窗,需要应用引导用户在系统应用“设置”的界面中手动授予权限。
-
系统权限弹窗不可被遮挡。
系统权限弹窗不可被其他组件/控件遮挡,弹窗信息需要完整展示,以便用户识别并完成授权动作。
如果系统权限弹窗与其他组件/控件同时同位置展示,系统权限弹窗将默认覆盖其他组件/控件。
-
每次执行需要目标权限的操作时,应用都必须检查自己是否已经具有该权限。
如需检查用户是否已向您的应用授予特定权限,可以使用checkAccessToken()函数,此方法会返回PermissionGranted或PermissionDenied。具体示例可参考下文。
-
每次访问受目标权限保护的接口之前,都需要使用requestPermissionsFromUser()接口请求相应的权限。
用户可能在动态授予权限后通过系统设置来取消应用的权限,因此不能将之前授予的授权状态持久化。
-
应用在onWindowStageCreate()回调中申请授权时,需要等待异步接口loadContent()/setUIContent()执行结束后或在loadContent()/setUIContent()回调中调用requestPermissionsFromUser(),否则在Content加载完成前,requestPermissionsFromUser会调用失败。
开发步骤
以申请使用位置权限为例进行说明。
效果展示:

-
申请ohos.permission.LOCATION、ohos.permission.APPROXIMATELY_LOCATION权限,配置方式请参见声明权限。
-
校验当前是否已经授权。
在进行权限申请之前,需要先检查当前应用程序是否已经被授予权限。可以通过调用checkAccessToken()方法来校验当前是否已经授权。如果已经授权,则可以直接访问目标操作,否则需要进行下一步操作,即向用户申请授权。
import kit.AbilityKit.{Permissions, AbilityAccessCtrl, GrantStatus, BundleManager, BundleFlag} import kit.PerformanceAnalysisKit.Hilog import ohos.bundle.bundle_manager.BundleInfo func checkPermissionGrant(permission: Permissions): GrantStatus { try { // 获取应用程序的accessTokenID let tokenID = BundleManager.getBundleInfoForSelf(BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).appInfo.accessTokenId let atManager = AbilityAccessCtrl.createAtManager() // 校验应用是否被授予权限 return atManager.checkAccessToken(tokenID, permission) } catch(e: Exception) { Hilog.error(0,"","checkAccessToken Exception: ${e}") throw e } } func checkPermissions(): Unit { let grantStatus1: Bool = (checkPermissionGrant("ohos.permission.LOCATION") == GrantStatus.PermissionGranted) let grantStatus2: Bool = (checkPermissionGrant("ohos.permission.APPROXIMATELY_LOCATION") == GrantStatus.PermissionDenied) // 精确定位权限(ohos.permission.LOCATION)只能跟模糊定位权限(ohos.permission.APPROXIMATELY_LOCATION)一起申请,或者已经有模糊定位权限才能申请精确定位权限 if (grantStatus2 && !grantStatus1) { // 模糊定位权限已申请,精确定位权限未申请 Hilog.info(0,"","Only APPROXIMATELY_LOCATION is granted") } else if (!grantStatus1 && !grantStatus2) { // 模糊定位权限和精确定位权限均未申请,需要申请模糊定位权限与精确定位权限,或单独申请模糊定位权限 Hilog.info(0,"","LOCATION and APPROXIMATELY_LOCATION not granted") } else { // 已经授权,可以继续访问目标操作 Hilog.info(0,"","LOCATION and APPROXIMATELY_LOCATION are granted") } } -
动态向用户申请授权。
动态向用户申请权限是指在应用程序运行时向用户请求授权的过程。可以通过调用requestPermissionsFromUser()方法来实现。该方法接收一个权限列表参数,例如位置、日历、相机、麦克风等。用户可以选择授予权限或者拒绝授权。
可以在Ability的onWindowStageCreate()回调中调用requestPermissionsFromUser()方法来动态申请权限,也可以根据业务需要在UI中向用户申请授权。
应用在onWindowStageCreate()回调中申请授权时,需要等待异步接口loadContent()/setUIContent()执行结束后或在loadContent()/setUIContent()回调中调用requestPermissionsFromUser(),否则在Content加载完成前,requestPermissionsFromUser会调用失败。
-
在UIAbility中向用户申请授权。
// main_ability.cj import kit.AbilityKit.* import kit.PerformanceAnalysisKit.Hilog import ohos.business_exception.* import ohos.window.WindowStage class MainAbility <: UIAbility { // ... public override func onWindowStageCreate(windowStage: WindowStage): Unit { Hilog.info(0,"","MainAbility onWindowStageCreate.") windowStage.loadContent("EntryView") // 设置回调 var resultCallback = { errorCode: Option<BusinessException>, data: Option<PermissionRequestResult> => match (errorCode) { case Some(e) => Hilog.error(0,"","requestPermissionsFromUser failed, errcode: ${e.code}") case _ => match (data) { case Some(value) => for (i in (0..value.permissions.size)) { if (value.authResults[i] == 0) { // 用户已授权 Hilog.info(0,"","permission: ${value.permissions[i]} is granted.") } else { // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 Hilog.info(0,"","permission: ${value.permissions[i]} is denied by user.") } } case _ => Hilog.error(0,"","requestPermissionsFromUser error: data is null") } } } let permissionList = ["ohos.permission.LOCATION", "ohos.permission.APPROXIMATELY_LOCATION"] let atManager = AbilityAccessCtrl.createAtManager() // 申请权限,requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗 atManager.requestPermissionsFromUser(this.context, permissionList, resultCallback) } } -
在UI中向用户申请授权。
-
获取context
// main_ability.cj import kit.AbilityKit.* import ohos.window.WindowStage import kit.PerformanceAnalysisKit.Hilog var globalAbilityContext: Option<UIAbilityContext> = Option<UIAbilityContext>.None class MainAbility <: UIAbility { public init() { super() registerSelf() } public override func onCreate(want: Want, launchParam: LaunchParam): Unit { Hilog.info(0,"","MainAbility OnCreated.${want.abilityName}") // 获取context globalAbilityContext = Option<UIAbilityContext>.Some(this.context) match (launchParam.launchReason) { case LaunchReason.StartAbility => Hilog.info(0,"","START_ABILITY") case _ => () } } public override func onWindowStageCreate(windowStage: WindowStage): Unit { Hilog.info(0,"","MainAbility onWindowStageCreate.") windowStage.loadContent("EntryView") } } -
申请权限
// index.cj import kit.AbilityKit.* import ohos.business_exception.* import kit.PerformanceAnalysisKit.Hilog import ohos.arkui.component.button.Button import ohos.arkui.state_macro_manage.Entry import ohos.arkui.state_macro_manage.Component @Entry @Component class EntryView { // 申请权限 func requestPermissons(): Unit { var resultCallback = { errorCode: Option<BusinessException>, data: Option<PermissionRequestResult> => match (errorCode) { case Some(e) => Hilog.info(0,"","permissionResultCallBack request error: errcode: ${e.code}") case _ => match (data) { case Some(value) => for (i in (0..value.permissions.size)) { if (value.authResults[i] == 0) { // 用户已授权 Hilog.info(0,"","permission: ${value.permissions[i]} is granted.") } else { // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 Hilog.info(0,"","permission: ${value.permissions[i]} is denied by user.") } } case _ => Hilog.info(0,"","permissionResultCallBack request error: data is null") } } } let atManager = AbilityAccessCtrl.createAtManager() let stageContext = globalAbilityContext.getOrThrow() let permissionList = ["ohos.permission.LOCATION", "ohos.permission.APPROXIMATELY_LOCATION"] atManager.requestPermissionsFromUser(stageContext, permissionList, resultCallback) } func build() { Row { Column { Button("requestPermissons").onClick ({ evt => Hilog.info(0,"","Hello Cangjie") // 点击按钮进行权限申请 requestPermissons() }).fontSize(30).height(50) }.width(100.percent) }.height(100.percent) } }
-
-
-
处理授权结果。
调用requestPermissionsFromUser()方法后,应用程序将等待用户授权的结果。如果用户授权,则可以继续访问目标操作。如果用户拒绝授权,则需要提示用户必须授权才能访问当前页面的功能,并引导用户到系统应用“设置”中打开相应的权限。
路径:设置 > 隐私 > 权限管理 > 应用 > 目标应用