应用权限申请开发实战 原创
一、简介
系统为应用访问系统资源提供了系统 Picker 与安全控件这两种便利途径。这两种途径皆凭借系统的独立进程达成,在应用拉起系统 Picker 或者呈现安全控件时,唯有依靠用户的主动操作才能够获取资源或结果。如此流程让应用无需额外申请权限,并且因用户的主动参与,对用户隐私与安全的保护得以进一步强化。
为了应用能够发挥其完整功能,可能需要访问系统的特定资源,而这些资源的访问通常需要获得相应的权限许可。
若用户拒绝了某项权限申请,应用应避免二次弹框申请该权限,应该在页面内的合适位置添加清晰的提示语,引导用户开启权限或退出当前需要该权限的场景,直至用户再次触发时再引导用户进行授权。
二、申请权限流程
对于user_grant类型权限在配置文件声明权限后还需要向用户请求授权,经过用户允许后才能获得权限
(1)判断当前是否已经授权,如果已经授权,则可以直接访问目标操作
(2)如果未授权,调用requestPermissionsFromUser()方法向用户申请授权
(3)返回结果authResults字段为0则表示用户已经授权,则可以继续访问目标操作;
authResults字段为-1则表示用户没有授权,这时需要判断返回结果的dialogShownResult
(4)如果dialogShownResults结果为true表面用户拒绝了授权,应用需要在页面内合适的位置添加提示语引导用户开启权限或者退出该场景
(5)dialogShownResults结果为false表示应用没有授权且还未展示授权的弹框,此时调用requestPermissionOnSetting()方法直接拉起权限设置弹框
三、以申请麦克风权限为例
未授权展示弹窗
在页面内合适的位置添加提示语引导用户开启权限或者退出该场景
拉起权限设置弹框
四、核心代码实现
(1)查询权限是否已授权
checkPermissionGrant(): void {
let hasPermission = false;
let tokenId: number = 0;
try {
let bundleInfo: bundleManager.BundleInfo =
bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
tokenId = appInfo.accessTokenId;
} catch (error) {
}
try {
let atManager = abilityAccessCtrl.createAtManager();
let microphone = atManager.checkAccessTokenSync(tokenId, 'ohos.permission.MICROPHONE');
hasPermission = microphone === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED
} catch (error) {
}
if (hasPermission) {
promptAction.showToast({
message: "已授权,可继续进行操作"
})
} else {
this.requestPermissions();
}
}
(2)申请权限
requestPermissions(): void {
let atManager = abilityAccessCtrl.createAtManager();
try {
atManager.requestPermissionsFromUser(this.context, ['ohos.permission.MICROPHONE']).then((data) => {
if (data.authResults[0] === -1) {
if (data.dialogShownResults && (data.dialogShownResults[0])) {
this.isShowPermissions = true;
if (data.authResults[0] === -1) {
this.permissionsMessage = "没有获得麦克风权限";
}
} else {
this.openPermissionsSetting();
return;
}
} else {
this.isShowPermissions = false;
}
if (data.authResults[0] !== 0) {
return;
}
promptAction.showToast({
message: "已授权,可继续进行操作"
})
}).catch((err: Error) => {
});
} catch (err) {
}
}
(3)引导用户授权弹窗
private openPermissionsSetting(): void {
let atManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionOnSetting(this.context, ['ohos.permission.MICROPHONE'])
.then((data: Array<abilityAccessCtrl.GrantStatus>) => {
if (data[0] === -1) {
this.isShowPermissions = true;
this.permissionsMessage = "没有获得麦克风权限";
return;
} else if (data[0] === 0) {
this.isShowPermissions = false;
promptAction.showToast({
message: "已授权,可继续进行操作"
})
} else {
this.isShowPermissions = false;
}
})
.catch((err: BusinessError) => {
});
}
五、注意事项
requestPermissionOnSetting()方法在调用前需要先调用requestPermissionsFromUser()方法。
若用户点击了“本次使用允许”,则下次申请权限应该调用requestPermissionsFromUser()方法,而不能直接调用requestPermissionOnSetting()方法。
六、完整代码
import { abilityAccessCtrl, bundleManager, common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
@State isShowPermissions: boolean = false;
@State permissionsMessage: string | Resource = "";
private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
build() {
Column({ space: 10 }) {
Column() {
if (this.isShowPermissions) {
Text() {
Span(this.permissionsMessage)
Span("开启权限")
.fontColor('#0A59F7')
.onClick(() => {
this.checkPermissionGrant();
})
}
.width('100%')
.padding({
left: 16,
right: 16
})
.margin({
bottom: 16
})
}
}.justifyContent(FlexAlign.End)
.layoutWeight(1)
Button("开启麦克风权限")
.onClick(() => {
this.checkPermissionGrant();
})
.backgroundColor('#0A59F7')
.width(288)
.margin({
bottom: 16
})
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.height('100%')
}
private openPermissionsSetting(): void {
let atManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionOnSetting(this.context, ['ohos.permission.MICROPHONE'])
.then((data: Array<abilityAccessCtrl.GrantStatus>) => {
if (data[0] === -1) {
this.isShowPermissions = true;
this.permissionsMessage = "没有获得麦克风权限";
return;
} else if (data[0] === 0) {
this.isShowPermissions = false;
promptAction.showToast({
message: "已授权,可继续进行操作"
})
} else {
this.isShowPermissions = false;
}
})
.catch((err: BusinessError) => {
});
}
checkPermissionGrant(): void {
let hasPermission = false;
let tokenId: number = 0;
try {
let bundleInfo: bundleManager.BundleInfo =
bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
tokenId = appInfo.accessTokenId;
} catch (error) {
}
try {
let atManager = abilityAccessCtrl.createAtManager();
let microphone = atManager.checkAccessTokenSync(tokenId, 'ohos.permission.MICROPHONE');
hasPermission = microphone === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED
} catch (error) {
}
if (hasPermission) {
promptAction.showToast({
message: "已授权,可继续进行操作"
})
} else {
this.requestPermissions();
}
}
requestPermissions(): void {
let atManager = abilityAccessCtrl.createAtManager();
try {
atManager.requestPermissionsFromUser(this.context, ['ohos.permission.MICROPHONE']).then((data) => {
if (data.authResults[0] === -1) {
if (data.dialogShownResults && (data.dialogShownResults[0])) {
this.isShowPermissions = true;
if (data.authResults[0] === -1) {
this.permissionsMessage = "没有获得麦克风权限";
}
} else {
this.openPermissionsSetting();
return;
}
} else {
this.isShowPermissions = false;
}
if (data.authResults[0] !== 0) {
return;
}
promptAction.showToast({
message: "已授权,可继续进行操作"
})
}).catch((err: Error) => {
});
} catch (err) {
}
}
}