鸿蒙学习实战之路-STG系列(10/11)-应用访问限制-解除限制
解除应用访问限制功能可以让你解除对指定应用的访问限制,让用户恢复正常访问。解除应用访问限制功能可以让你轻松解除对应用的访问限制,让用户恢复正常访问。限制和解除必须对称使用,类型必须匹配禁止清单解除时,必须包含所有之前限制的应用不能多传应用,多传或 token 无效都会报错其他应用管控的应用不会被解除应用 Token 需要保存好,用于后续解除限制空列表有特殊含义,要根据限制类型正确理解解除应用访问限
鸿蒙学习实战之路-STG系列(10/11)-应用访问限制-解除限制
朋友们,上一篇我们学习了如何设置应用访问限制。今天这篇我们来学习如何解除应用访问限制 - 这就像是给你的应用"解除封禁"或"重新开放" o(╯□╰)o
解除应用访问限制功能可以让你解除对某些应用的访问限制,让用户恢复正常访问。这就像给孩子"解除游戏限制",让他们可以正常使用了~
今天这篇,我会手把手带你实现应用访问限制的解除功能,全程不超过5分钟(不含你测试的时间)~
一、解除应用访问限制概述
解除应用访问限制功能可以让你解除对指定应用的访问限制,让用户恢复正常访问。
1. 业务流程
应用调用解除应用访问限制接口
↓
系统检查应用是否有权限、用户是否授权
↓
如果没有权限 → 抛出错误码
如果有权限 → 解析参数
↓
判断传入的应用列表是否被其他应用或健康使用设备管控
↓
如果有被其他应用管控 → 对应应用不解除限制
如果没有被其他应用管控 → 解除限制
↓
返回处理结果
2. 限制和解除的对称性
🥦 西兰花警告:
同一个管控应用的限制和解除限制必须对称使用,即解除限制必须和其限制的类型匹配上!
- 如果之前用的是禁止清单设置限制,解除时也必须用禁止清单
- 如果之前用的是允许清单设置限制,解除时也必须用允许清单
- 类型不匹配或之前没有做过限制,都会报参数错误
二、核心接口
解除应用访问限制的核心接口:
| 接口名 | 说明 |
|---|---|
releaseAppsRestriction(appInfo, restrictionType) |
根据应用 token 数组和限制类型,解除应用访问限制 |
接口参数说明
appInfo: 应用信息对象,包含appTokens数组restrictionType: 限制类型,可以是BLOCKLIST_TYPE或ALLOWLIST_TYPE
边界场景
🥦 西兰花警告:
-
空列表 + 禁止清单: 如果传入的应用列表为空,限制类型为禁止清单,则不对任何应用做解除限制
-
空列表 + 允许清单: 如果传入的应用列表为空,限制类型为允许清单,则对除了系统内置允许清单应用、管控发起应用本身、已授权的管控应用和健康使用设备之外的所有应用做解除限制
-
必须对称使用: 解除限制必须和限制的类型匹配,不匹配或之前没有做过限制都是参数错误
-
禁止清单解除要完整: 如果之前用禁止清单方式做限制,解除时传入的应用列表必须包含所有的禁用清单应用,才可全部解除
-
禁止清单不能多传: 如果按禁止清单方式解除限制时,传入的应用名单里包含了不在之前限制禁用清单中的应用(或 token 无效),则为参数错误
-
允许清单不能多传: 如果按允许清单方式解除限制时,传入的应用名单里包含了不在之前允许清单中的应用(或 token 无效),则为参数错误
三、开发步骤
步骤 1: 导入相关模块
import { guardService, appPicker } from '@kit.ScreenTimeGuardKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
步骤 2: 实现应用访问限制解除功能
@Entry
@Component
struct ReleaseAppsRestrictionDemo {
@State selectedTokens: string[] = [];
@State restrictionType: string = 'BLOCKLIST_TYPE';
@State message: string = '';
/**
* 选择要解除限制的应用
*/
async selectApps() {
try {
const tokens = await appPicker.startAppPicker(
this.getUIContext().getHostContext() as common.UIAbilityContext,
{ appTokens: this.selectedTokens }
);
this.selectedTokens = tokens;
this.message = `已选择 ${tokens.length} 个应用`;
hilog.info(0x0000, 'ReleaseAppsRestrictionDemo',
`selected ${tokens.length} apps`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `选择应用失败: ${message}`;
hilog.error(0x0000, 'ReleaseAppsRestrictionDemo',
`startAppPicker failed with error code: ${code}, message: ${message}`);
}
}
/**
* 解除应用访问限制
*/
async releaseRestriction() {
if (this.selectedTokens.length === 0) {
this.message = '请先选择要解除限制的应用';
return;
}
try {
const appInfo: guardService.AppInfo = {
appTokens: this.selectedTokens
};
const restrictionType: guardService.RestrictionType =
this.restrictionType === 'BLOCKLIST_TYPE'
? guardService.RestrictionType.BLOCKLIST_TYPE
: guardService.RestrictionType.ALLOWLIST_TYPE;
await guardService.releaseAppsRestriction(appInfo, restrictionType);
this.message = `应用访问限制解除成功 (${this.getRestrictionTypeDesc()})`;
hilog.info(0x0000, 'ReleaseAppsRestrictionDemo',
`releaseAppsRestriction succeeded with type: ${this.restrictionType}`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `解除失败: ${message}`;
hilog.error(0x0000, 'ReleaseAppsRestrictionDemo',
`releaseAppsRestriction failed with error code: ${code}, message: ${message}`);
}
}
/**
* 获取限制类型描述
*/
getRestrictionTypeDesc(): string {
return this.restrictionType === 'BLOCKLIST_TYPE' ? '禁止清单' : '允许清单';
}
build() {
Column() {
Text('应用访问限制解除演示')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 40 })
Text(this.message)
.fontSize(14)
.margin({ top: 20 })
.fontColor('#666666')
// 限制类型选择
Text('限制类型 (必须与设置时一致)')
.fontSize(16)
.margin({ top: 30 })
Row() {
Button('禁止清单')
.onClick(() => { this.restrictionType = 'BLOCKLIST_TYPE'; })
.backgroundColor(this.restrictionType === 'BLOCKLIST_TYPE' ? '#007DFF' : '#F5F5F5')
.fontColor(this.restrictionType === 'BLOCKLIST_TYPE' ? '#FFFFFF' : '#000000')
.margin({ right: 10 })
Button('允许清单')
.onClick(() => { this.restrictionType = 'ALLOWLIST_TYPE'; })
.backgroundColor(this.restrictionType === 'ALLOWLIST_TYPE' ? '#007DFF' : '#F5F5F5')
.fontColor(this.restrictionType === 'ALLOWLIST_TYPE' ? '#FFFFFF' : '#000000')
.margin({ left: 10 })
}
.margin({ top: 10 })
.width('80%')
// 限制类型说明
Text(this.getRestrictionTypeDesc() + ': ' +
(this.restrictionType === 'BLOCKLIST_TYPE'
? '解除禁止清单中应用的限制'
: '解除允许清单方式设置的限制'))
.fontSize(14)
.margin({ top: 10 })
.fontColor('#666666')
// 应用选择
Text('选择要解除限制的应用')
.fontSize(16)
.margin({ top: 30 })
Button('选择应用')
.onClick(() => this.selectApps())
.margin({ top: 10 })
.width('80%')
Text(`已选择 ${this.selectedTokens.length} 个应用`)
.fontSize(14)
.margin({ top: 5 })
.fontColor('#666666')
// 解除按钮
Button('解除限制')
.onClick(() => this.releaseRestriction())
.margin({ top: 30 })
.width('80%')
}
.width('100%')
.height('100%')
.padding(20)
}
}
四、完整示例代码
下面是一个更完整的示例,集成了设置和解除应用访问限制的完整功能:
import { guardService, appPicker } from '@kit.ScreenTimeGuardKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';
@Entry
@Component
struct AppsRestrictionCompleteManagement {
// 状态变量
@State authStatus: string = '未知';
@State selectedTokens: string[] = [];
@State restrictionType: string = 'BLOCKLIST_TYPE';
@State isRestricted: boolean = false;
@State message: string = '';
@State currentTab: number = 0;
// 用户首选项
private pref: preferences.Preferences | null = null;
async aboutToAppear() {
// 初始化用户首选项
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
this.pref = await preferences.getPreferences(context, 'apps_restriction_complete_data');
// 加载保存的状态
await this.loadStatus();
// 检查授权状态
await this.checkAuthStatus();
}
/**
* 加载保存的状态
*/
async loadStatus() {
try {
if (this.pref) {
const tokens = await this.pref.get('selected_tokens', '') as string;
if (tokens) {
this.selectedTokens = JSON.parse(tokens);
}
const type = await this.pref.get('restriction_type', 'BLOCKLIST_TYPE') as string;
this.restrictionType = type;
const restricted = await this.pref.get('is_restricted', false) as boolean;
this.isRestricted = restricted;
}
} catch (err) {
hilog.error(0x0000, 'AppsRestrictionCompleteManagement', 'loadStatus failed');
}
}
/**
* 保存状态
*/
async saveStatus() {
try {
if (this.pref) {
await this.pref.put('selected_tokens', JSON.stringify(this.selectedTokens));
await this.pref.put('restriction_type', this.restrictionType);
await this.pref.put('is_restricted', this.isRestricted);
await this.pref.flush();
}
} catch (err) {
hilog.error(0x0000, 'AppsRestrictionCompleteManagement', 'saveStatus failed');
}
}
/**
* 检查授权状态
*/
async checkAuthStatus() {
try {
const status = await guardService.getUserAuthStatus();
this.authStatus = status === guardService.AuthStatus.AUTHORIZED ? '已授权' : '未授权';
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
hilog.error(0x0000, 'AppsRestrictionCompleteManagement',
`checkAuthStatus failed with error code: ${code}, message: ${message}`);
}
}
/**
* 请求用户授权
*/
async requestAuth() {
try {
await guardService.requestUserAuth(
this.getUIContext().getHostContext() as common.UIAbilityContext
);
await this.checkAuthStatus();
this.message = '授权成功';
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `授权失败: ${message}`;
hilog.error(0x0000, 'AppsRestrictionCompleteManagement',
`requestUserAuth failed with error code: ${code}, message: ${message}`);
}
}
/**
* 选择应用
*/
async selectApps() {
try {
const tokens = await appPicker.startAppPicker(
this.getUIContext().getHostContext() as common.UIAbilityContext,
{ appTokens: this.selectedTokens }
);
this.selectedTokens = tokens;
this.message = `已选择 ${tokens.length} 个应用`;
hilog.info(0x0000, 'AppsRestrictionCompleteManagement',
`selected ${tokens.length} apps`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `选择应用失败: ${message}`;
hilog.error(0x0000, 'AppsRestrictionCompleteManagement',
`startAppPicker failed with error code: ${code}, message: ${message}`);
}
}
/**
* 设置应用访问限制
*/
async setRestriction() {
if (this.selectedTokens.length === 0) {
this.message = '请先选择要限制的应用';
return;
}
try {
const appInfo: guardService.AppInfo = {
appTokens: this.selectedTokens
};
const restrictionType: guardService.RestrictionType =
this.restrictionType === 'BLOCKLIST_TYPE'
? guardService.RestrictionType.BLOCKLIST_TYPE
: guardService.RestrictionType.ALLOWLIST_TYPE;
await guardService.setAppsRestriction(appInfo, restrictionType);
this.isRestricted = true;
await this.saveStatus();
this.message = `应用访问限制设置成功 (${this.getRestrictionTypeDesc()})`;
hilog.info(0x0000, 'AppsRestrictionCompleteManagement',
`setAppsRestriction succeeded with type: ${this.restrictionType}`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `设置失败: ${message}`;
hilog.error(0x0000, 'AppsRestrictionCompleteManagement',
`setAppsRestriction failed with error code: ${code}, message: ${message}`);
}
}
/**
* 解除应用访问限制
*/
async releaseRestriction() {
if (this.selectedTokens.length === 0) {
this.message = '请先选择要解除限制的应用';
return;
}
try {
const appInfo: guardService.AppInfo = {
appTokens: this.selectedTokens
};
const restrictionType: guardService.RestrictionType =
this.restrictionType === 'BLOCKLIST_TYPE'
? guardService.RestrictionType.BLOCKLIST_TYPE
: guardService.RestrictionType.ALLOWLIST_TYPE;
await guardService.releaseAppsRestriction(appInfo, restrictionType);
this.isRestricted = false;
this.selectedTokens = [];
await this.saveStatus();
this.message = `应用访问限制解除成功 (${this.getRestrictionTypeDesc()})`;
hilog.info(0x0000, 'AppsRestrictionCompleteManagement',
`releaseAppsRestriction succeeded with type: ${this.restrictionType}`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `解除失败: ${message}`;
hilog.error(0x0000, 'AppsRestrictionCompleteManagement',
`releaseAppsRestriction failed with error code: ${code}, message: ${message}`);
}
}
/**
* 获取限制类型描述
*/
getRestrictionTypeDesc(): string {
return this.restrictionType === 'BLOCKLIST_TYPE' ? '禁止清单' : '允许清单';
}
/**
* 获取限制类型说明
*/
getRestrictionTypeDescDetail(): string {
if (this.restrictionType === 'BLOCKLIST_TYPE') {
return '禁止访问选中的应用';
} else {
return '只允许访问选中的应用';
}
}
build() {
Column() {
Text('应用访问限制完整管理')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 40 })
// 消息显示
Text(this.message)
.fontSize(14)
.margin({ top: 10 })
.fontColor('#666666')
// 授权状态
Row() {
Text('授权状态: ' + this.authStatus)
.fontSize(16)
.margin({ top: 20 })
if (this.authStatus === '已授权') {
Text('✓')
.fontSize(16)
.fontColor('#00FF00')
.margin({ left: 10 })
} else {
Button('请求授权')
.onClick(() => this.requestAuth())
.margin({ left: 10 })
}
}
.margin({ top: 10 })
.width('100%')
.padding({ left: 20, right: 20 })
.backgroundColor('#F5F5F5')
.borderRadius(8)
// 限制状态
Row() {
Text('限制状态: ' + (this.isRestricted ? '已开启' : '未开启'))
.fontSize(16)
.margin({ top: 20 })
if (this.isRestricted) {
Text('✓')
.fontSize(16)
.fontColor('#00FF00')
.margin({ left: 10 })
}
}
.margin({ top: 10 })
.width('100%')
.padding({ left: 20, right: 20 })
.backgroundColor('#F5F5F5')
.borderRadius(8)
// Tab 切换
Row() {
Button('设置限制')
.onClick(() => { this.currentTab = 0; })
.backgroundColor(this.currentTab === 0 ? '#007DFF' : '#F5F5F5')
.fontColor(this.currentTab === 0 ? '#FFFFFF' : '#000000')
.margin({ right: 10 })
Button('解除限制')
.onClick(() => { this.currentTab = 1; })
.backgroundColor(this.currentTab === 1 ? '#007DFF' : '#F5F5F5')
.fontColor(this.currentTab === 1 ? '#FFFFFF' : '#000000')
.margin({ left: 10 })
}
.margin({ top: 20 })
.width('80%')
// Tab 内容
if (this.currentTab === 0) {
// 设置限制页面
Column() {
// 限制类型选择
Text('限制类型')
.fontSize(16)
.margin({ top: 30 })
Row() {
Button('禁止清单')
.onClick(() => { this.restrictionType = 'BLOCKLIST_TYPE'; })
.backgroundColor(this.restrictionType === 'BLOCKLIST_TYPE' ? '#007DFF' : '#F5F5F5')
.fontColor(this.restrictionType === 'BLOCKLIST_TYPE' ? '#FFFFFF' : '#000000')
.margin({ right: 10 })
Button('允许清单')
.onClick(() => { this.restrictionType = 'ALLOWLIST_TYPE'; })
.backgroundColor(this.restrictionType === 'ALLOWLIST_TYPE' ? '#007DFF' : '#F5F5F5')
.fontColor(this.restrictionType === 'ALLOWLIST_TYPE' ? '#FFFFFF' : '#000000')
.margin({ left: 10 })
}
.margin({ top: 10 })
.width('80%')
// 限制类型说明
Text(this.getRestrictionTypeDesc() + ': ' + this.getRestrictionTypeDescDetail())
.fontSize(14)
.margin({ top: 10 })
.fontColor('#666666')
// 应用选择
Text('选择要限制的应用')
.fontSize(16)
.margin({ top: 30 })
Button('选择应用')
.onClick(() => this.selectApps())
.margin({ top: 10 })
.width('80%')
Text(`已选择 ${this.selectedTokens.length} 个应用`)
.fontSize(14)
.margin({ top: 5 })
.fontColor('#666666')
// 设置按钮
Button('设置限制')
.onClick(() => this.setRestriction())
.margin({ top: 30 })
.width('80%')
}
.width('100%')
.height('100%')
} else {
// 解除限制页面
Column() {
// 限制类型选择
Text('限制类型 (必须与设置时一致)')
.fontSize(16)
.margin({ top: 30 })
Row() {
Button('禁止清单')
.onClick(() => { this.restrictionType = 'BLOCKLIST_TYPE'; })
.backgroundColor(this.restrictionType === 'BLOCKLIST_TYPE' ? '#007DFF' : '#F5F5F5')
.fontColor(this.restrictionType === 'BLOCKLIST_TYPE' ? '#FFFFFF' : '#000000')
.margin({ right: 10 })
Button('允许清单')
.onClick(() => { this.restrictionType = 'ALLOWLIST_TYPE'; })
.backgroundColor(this.restrictionType === 'ALLOWLIST_TYPE' ? '#007DFF' : '#F5F5F5')
.fontColor(this.restrictionType === 'ALLOWLIST_TYPE' ? '#FFFFFF' : '#000000')
.margin({ left: 10 })
}
.margin({ top: 10 })
.width('80%')
// 限制类型说明
Text(this.getRestrictionTypeDesc() + ': ' +
(this.restrictionType === 'BLOCKLIST_TYPE'
? '解除禁止清单中应用的限制'
: '解除允许清单方式设置的限制'))
.fontSize(14)
.margin({ top: 10 })
.fontColor('#666666')
// 应用选择
Text('选择要解除限制的应用')
.fontSize(16)
.margin({ top: 30 })
Button('选择应用')
.onClick(() => this.selectApps())
.margin({ top: 10 })
.width('80%')
Text(`已选择 ${this.selectedTokens.length} 个应用`)
.fontSize(14)
.margin({ top: 5 })
.fontColor('#666666')
// 解除按钮
Button('解除限制')
.onClick(() => this.releaseRestriction())
.margin({ top: 30 })
.width('80%')
}
.width('100%')
.height('100%')
}
}
.width('100%')
.height('100%')
.padding(20)
}
}
五、注意事项
🥦 西兰花警告:
-
必须先获得用户授权: 解除应用访问限制之前,必须先请求用户授权,否则会报错
-
限制和解除必须对称:
- 如果之前用的是禁止清单设置限制,解除时也必须用禁止清单
- 如果之前用的是允许清单设置限制,解除时也必须用允许清单
- 类型不匹配会报参数错误
-
空列表的特殊含义:
- 空列表 + 禁止清单 = 不解除任何应用限制
- 空列表 + 允许清单 = 解除除系统应用、管控应用外的所有应用限制
-
禁止清单解除要完整:
- 如果之前用禁止清单方式做限制,解除时传入的应用列表必须包含所有的禁用清单应用
- 不能只解除部分应用,要么全部解除,要么都不解除
-
不能多传应用:
- 禁止清单解除时,传入的应用名单不能包含不在之前限制禁用清单中的应用
- 允许清单解除时,传入的应用名单不能包含不在之前允许清单中的应用
- 多传或 token 无效都会报参数错误
-
其他应用管控不受影响: 如果某个应用被其他三方应用或健康使用设备设置的策略管控,则对应应用不会解除限制
-
应用 Token 要保存: 应用 Token 需要保存好,用于后续的解除限制操作
六、使用场景
解除应用访问限制功能可以用于以下场景:
1. 家长控制
- 解除游戏限制: 允许孩子在特定时间访问游戏
- 解除社交限制: 允许孩子访问社交应用
2. 专注模式
- 工作时间结束后解除限制: 允许访问娱乐应用
- 休息时间解除限制: 允许访问各种应用
3. 设备共享
- 设备收回后解除限制: 恢复正常应用访问权限
- 临时解除限制: 允许访问特定应用
七、文档资源
官方文档链接:
八、总结
解除应用访问限制功能可以让你轻松解除对应用的访问限制,让用户恢复正常访问。
核心要点:
- 限制和解除必须对称使用,类型必须匹配
- 禁止清单解除时,必须包含所有之前限制的应用
- 不能多传应用,多传或 token 无效都会报错
- 其他应用管控的应用不会被解除
- 应用 Token 需要保存好,用于后续解除限制
- 空列表有特殊含义,要根据限制类型正确理解
解除应用访问限制就像是给应用"解除封禁",让用户恢复正常访问权限。但要记住,限制和解除必须对称使用 _
下一步行动
建议你:
- 先请求用户授权
- 测试设置限制功能
- 测试解除限制功能
- 测试对称性要求(类型不匹配的情况)
- 测试禁止清单的完整解除要求
- 测试多传应用的错误情况
- 结合下一篇的完整实战案例,实现一个完整的家长控制应用
记住,不教理论,只给你能跑的代码和避坑指南! _
我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦
更多推荐




所有评论(0)