鸿蒙学习实战之路-STG系列(4/11)-应用选择页功能详解
应用选择页是 Screen Time Guard Kit 提供的一个半模态页面,让用户可以方便地选择要管控的应用。应用选择页是 Screen Time Guard Kit 提供的便捷功能,让用户可以方便地选择要管控的应用。应用选择页让用户选择要管控的应用系统返回应用的 Token,用于后续的管控操作许可应用跳转页用于管控期间快速访问许可应用Token 不包含应用的敏感信息,保护用户隐私系统关键应用
鸿蒙学习实战之路-STG系列(4/11)-应用选择页功能详解
朋友们,前三篇我们学习了 Screen Time Guard Kit 的基本概念、开发准备和用户授权管理。今天这篇我们就来学习如何使用应用选择页功能,包括拉起应用选择页和拉起许可应用跳转页 o(╯□╰)o
应用选择页就像是"点菜系统",用户可以在一个半模态页面中选择自己想要管控的应用,系统会返回应用的 token。有了 token,就可以对选中的应用进行管控了~
今天这篇,我会手把手带你实现应用选择页的完整功能,全程不超过5分钟(不含你测试的时间)~
一、什么是应用选择页?
应用选择页是 Screen Time Guard Kit 提供的一个半模态页面,让用户可以方便地选择要管控的应用。
1. 两种应用选择页
| 类型 | 说明 | 适用场景 |
|---|---|---|
| 应用选择页 | 用户可以选择要管控的应用 | 设置管控策略、设置应用访问限制 |
| 许可应用跳转页 | 展示用户可以使用的许可应用,点击可跳转 | 管控期间快速访问许可应用 |
2. 应用 Token 是什么?
Token 就像是应用的"身份证号",系统用它来唯一标识一个应用。Token 不包含应用的包名、应用名等敏感信息,保护用户隐私安全 _
🥦 西兰花小贴士:
Token 是系统生成的唯一标识,开发者无法获取到应用的包名和应用名,这样既保护了用户隐私,又防止了开发者滥用~
二、拉起应用选择页
拉起应用选择页是最常用的功能,就像让用户在菜单上点菜一样。
1. 业务流程
拉起应用选择页的流程就像这样:
应用调用拉起应用选择页接口
↓
系统检查应用是否有权限、用户是否授权
↓
如果没有权限 → 抛出错误码
如果有权限 → 拉起应用选择列表
↓
如果传入 token → 预勾选对应的应用
如果没传入 token → 不预勾选
↓
用户选择应用后点击完成
↓
返回用户选中的应用 token 列表
2. 核心接口
拉起应用选择页的接口:
| 接口名 | 说明 |
|---|---|
startAppPicker(context, appSelection) |
拉起应用选择页,返回选中的应用 token 列表 |
3. 应用列表说明
应用选择页中的应用列表有一些限制:
| 不包含的应用类型 | 说明 |
|---|---|
| 系统关键应用 | 电话、联系人、设置、未成年模式等 |
| 管控发起应用本身 | 你的应用本身不会出现在列表中 |
| 已授权的管控应用 | 其他已经获得管控权限的应用 |
🥦 西兰花小贴士:
系统关键应用不能被管控,这是为了保障手机的基本功能正常运行。这个限制也合理吧? (┓( ´∀` )┏
4. 开发步骤
步骤 1: 导入相关模块
import { appPicker } from '@kit.ScreenTimeGuardKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
步骤 2: 拉起应用选择页
@Entry
@Component
struct AppPickerDemo {
@State selectedTokens: string[] = [];
@State selectedCount: number = 0;
build() {
Column() {
Text('应用选择页演示')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 40 })
Text('已选择应用数量: ' + this.selectedCount)
.fontSize(18)
.margin({ top: 30 })
Button('拉起应用选择页')
.onClick(async () => {
try {
// 拉起应用选择页
const tokens = await appPicker.startAppPicker(
this.getUIContext().getHostContext() as common.UIAbilityContext,
{ appTokens: this.selectedTokens } // 传入已选择的 token,用于预勾选
);
this.selectedTokens = tokens;
this.selectedCount = tokens.length;
hilog.info(0x0000, 'AppPickerDemo',
`selected tokens: ${JSON.stringify(tokens)}`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
hilog.error(0x0000, 'AppPickerDemo',
`startAppPicker failed with error code: ${code}, message: ${message}`);
}
})
.margin({ top: 30 })
.width('80%')
Button('清空选择')
.onClick(() => {
this.selectedTokens = [];
this.selectedCount = 0;
})
.margin({ top: 10 })
.width('80%')
}
.width('100%')
.height('100%')
.padding(20)
}
}
🥦 西兰花小贴士:
传入 appTokens 参数可以实现预勾选功能,用户再次打开选择页时会看到之前选中的应用~
三、拉起许可应用跳转页
许可应用跳转页是 6.0.2(22) 版本新增的功能,用于在被管控期间快速访问许可应用。
1. 业务流程
拉起许可应用跳转页的流程就像这样:
应用调用拉起许可应用跳转页接口
↓
系统检查应用是否有权限、用户是否授权
↓
如果没有权限 → 抛出错误码
如果有权限 → 获取全量应用信息
↓
判断是否显示 TrustApp(可信应用)
↓
拉起应用列表 Form
↓
用户点击应用图标
↓
跳转到对应的应用
2. 核心接口
拉起许可应用跳转页的接口:
| 接口名 | 说明 |
|---|---|
startAppForm(context, appSelection, appSubTitle, displayTrustApp) |
拉起许可应用跳转页 |
参数说明:
context: 应用上下文appSelection: 应用信息,包含 token 列表appSubTitle: 页面副标题displayTrustApp: 是否显示可信应用
3. 开发步骤
@Entry
@Component
struct AppFormDemo {
@State selectedTokens: string[] = [];
build() {
Column() {
Text('许可应用跳转页演示')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 40 })
Button('1. 先选择应用')
.onClick(async () => {
try {
// 先拉起应用选择页,获取 token
const tokens = await appPicker.startAppPicker(
this.getUIContext().getHostContext() as common.UIAbilityContext,
{ appTokens: [] }
);
this.selectedTokens = tokens;
hilog.info(0x0000, 'AppFormDemo',
`selected tokens: ${JSON.stringify(tokens)}`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
hilog.error(0x0000, 'AppFormDemo',
`startAppPicker failed with error code: ${code}, message: ${message}`);
}
})
.margin({ top: 30 })
.width('80%')
Button('2. 拉起许可应用跳转页')
.onClick(async () => {
if (this.selectedTokens.length === 0) {
hilog.warn(0x0000, 'AppFormDemo', '请先选择应用');
return;
}
try {
// 拉起许可应用跳转页
await appPicker.startAppForm(
this.getUIContext().getHostContext() as common.UIAbilityContext,
{ appTokens: this.selectedTokens },
'许可应用', // 页面副标题
false // 是否显示可信应用
);
hilog.info(0x0000, 'AppFormDemo', 'startAppForm succeeded');
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
hilog.error(0x0000, 'AppFormDemo',
`startAppForm failed with error code: ${code}, message: ${message}`);
}
})
.margin({ top: 10 })
.width('80%')
}
.width('100%')
.height('100%')
.padding(20)
}
}
🥦 西兰花小贴士:
许可应用跳转页通常用于管控期间,让用户快速访问一些允许使用的应用,比如学习类应用、通讯工具等~
四、完整示例代码
下面是一个完整的示例,展示了如何实现应用选择页的完整功能:
import { 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 AppPickerFullDemo {
@State selectedTokens: string[] = [];
@State selectedCount: number = 0;
@State lastUpdateTime: string = '';
private pref: preferences.Preferences | null = null;
async aboutToAppear() {
// 初始化用户首选项
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
this.pref = await preferences.getPreferences(context, 'app_picker_data');
// 加载之前保存的 token
await this.loadSelectedTokens();
}
/**
* 加载之前保存的 token
*/
async loadSelectedTokens() {
try {
if (this.pref) {
const tokens = await this.pref.get('selected_tokens', '') as string;
if (tokens) {
this.selectedTokens = JSON.parse(tokens);
this.selectedCount = this.selectedTokens.length;
}
const updateTime = await this.pref.get('last_update_time', '') as string;
this.lastUpdateTime = updateTime;
}
} catch (err) {
hilog.error(0x0000, 'AppPickerFullDemo', 'loadSelectedTokens failed');
}
}
/**
* 保存 token
*/
async saveSelectedTokens() {
try {
if (this.pref) {
await this.pref.put('selected_tokens', JSON.stringify(this.selectedTokens));
await this.pref.put('last_update_time', new Date().toLocaleString());
await this.pref.flush();
this.lastUpdateTime = new Date().toLocaleString();
}
} catch (err) {
hilog.error(0x0000, 'AppPickerFullDemo', 'saveSelectedTokens failed');
}
}
/**
* 拉起应用选择页
*/
async startAppPicker() {
try {
const tokens = await appPicker.startAppPicker(
this.getUIContext().getHostContext() as common.UIAbilityContext,
{ appTokens: this.selectedTokens } // 传入已选择的 token,用于预勾选
);
this.selectedTokens = tokens;
this.selectedCount = tokens.length;
// 保存到用户首选项
await this.saveSelectedTokens();
hilog.info(0x0000, 'AppPickerFullDemo',
`selected tokens: ${JSON.stringify(tokens)}`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
hilog.error(0x0000, 'AppPickerFullDemo',
`startAppPicker failed with error code: ${code}, message: ${message}`);
}
}
/**
* 拉起许可应用跳转页
*/
async startAppForm() {
if (this.selectedTokens.length === 0) {
hilog.warn(0x0000, 'AppPickerFullDemo', '请先选择应用');
return;
}
try {
await appPicker.startAppForm(
this.getUIContext().getHostContext() as common.UIAbilityContext,
{ appTokens: this.selectedTokens },
'许可应用',
false
);
hilog.info(0x0000, 'AppPickerFullDemo', 'startAppForm succeeded');
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
hilog.error(0x0000, 'AppPickerFullDemo',
`startAppForm failed with error code: ${code}, message: ${message}`);
}
}
/**
* 清空选择
*/
clearSelection() {
this.selectedTokens = [];
this.selectedCount = 0;
this.lastUpdateTime = '';
}
build() {
Column() {
Text('应用选择页完整演示')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 40 })
Text('已选择应用数量: ' + this.selectedCount)
.fontSize(18)
.margin({ top: 30 })
if (this.lastUpdateTime) {
Text('最后更新时间: ' + this.lastUpdateTime)
.fontSize(14)
.margin({ top: 5 })
.fontColor('#999999')
}
Button('拉起应用选择页')
.onClick(() => this.startAppPicker())
.margin({ top: 30 })
.width('80%')
Button('拉起许可应用跳转页')
.onClick(() => this.startAppForm())
.margin({ top: 10 })
.width('80%')
Button('清空选择')
.onClick(() => this.clearSelection())
.margin({ top: 10 })
.width('80%')
}
.width('100%')
.height('100%')
.padding(20)
}
}
五、应用选择页的使用场景
应用选择页在很多场景下都非常有用:
1. 设置管控策略
用户可以选择要管控的应用,然后设置时间策略。
// 选择要管控的游戏应用
const tokens = await appPicker.startAppPicker(context, { appTokens: [] });
// 为选中的应用设置管控策略
const strategy: guardService.GuardStrategy = {
name: '游戏管控',
timeStrategy: {
type: guardService.TimeStrategyType.START_END_TIME_TYPE,
startTime: '09:00',
endTime: '18:00',
repeat: [1, 2, 3, 4, 5] // 周一到周五
},
appInfo: { appTokens: tokens },
appRestrictionType: guardService.RestrictionType.BLOCKLIST_TYPE
};
await guardService.addGuardStrategy(strategy);
2. 设置应用访问限制
用户可以选择要限制的应用,然后设置访问限制。
// 选择要限制的娱乐应用
const tokens = await appPicker.startAppPicker(context, { appTokens: [] });
// 设置应用访问限制
await guardService.setAppsRestriction(
{ appTokens: tokens },
guardService.RestrictionType.BLOCKLIST_TYPE
);
3. 管控期间快速访问许可应用
用户在被管控期间,可以快速访问一些许可应用。
// 显示学习类应用,让用户快速访问
const learningAppTokens = ['token1', 'token2', 'token3'];
await appPicker.startAppForm(
context,
{ appTokens: learningAppTokens },
'学习应用',
false
);
六、注意事项
🥦 西兰花警告:
- 必须先获得用户授权: 使用应用选择页之前,必须先请求用户授权,否则会报错
- 系统关键应用不能选择: 电话、联系人、设置等系统关键应用不会出现在列表中
- 管控发起应用不会出现: 你的应用本身不会出现在选择列表中
- Token 需要妥善保管: Token 是应用的身份标识,需要保存好,用于后续的管控操作
- 许可应用跳转页需要 Token: 拉起许可应用跳转页之前,需要先获取应用的 Token
- 版本要求: 许可应用跳转页功能需要 6.0.2(22) 及以上版本
七、文档资源
官方文档链接:
八、总结
应用选择页是 Screen Time Guard Kit 提供的便捷功能,让用户可以方便地选择要管控的应用。
核心要点:
- 应用选择页让用户选择要管控的应用
- 系统返回应用的 Token,用于后续的管控操作
- 许可应用跳转页用于管控期间快速访问许可应用
- Token 不包含应用的敏感信息,保护用户隐私
- 系统关键应用不能被管控
应用选择页就像"点菜系统",用户选好后,系统会给你一张"菜单"(Token 列表),然后就可以对这些应用进行管控了 _
下一步行动
建议你:
- 先实现基本的应用选择页功能
- 添加 Token 保存和加载功能
- 实现许可应用跳转页功能
- 结合用户授权管理,实现完整的流程
- 测试各种场景,确保功能正常
记住,不教理论,只给你能跑的代码和避坑指南! _
我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦
更多推荐


所有评论(0)