鸿蒙学习实战之路-STG系列(11/11)-Screen Time Guard Kit完整实战案例
朋友们,这是 STG 系列的最后一篇啦! 前面 10 篇我们学习了 Screen Time Guard Kit 的所有核心功能。今天这篇我们来做一个完整的实战案例 - 一个功能完善的家长控制应用 o(╯□╰)o这个实战案例会整合我们学过的所有功能,包括用户授权、应用选择、守护策略管理、应用访问限制等,让你可以一次性学会如何使用 Screen Time Guard Kit 构建一个完整的屏幕时间管控
鸿蒙学习实战之路-STG系列(11/11)-Screen Time Guard Kit完整实战案例
朋友们,这是 STG 系列的最后一篇啦! 前面 10 篇我们学习了 Screen Time Guard Kit 的所有核心功能。今天这篇我们来做一个完整的实战案例 - 一个功能完善的家长控制应用 o(╯□╰)o
这个实战案例会整合我们学过的所有功能,包括用户授权、应用选择、守护策略管理、应用访问限制等,让你可以一次性学会如何使用 Screen Time Guard Kit 构建一个完整的屏幕时间管控应用~
今天这篇,我会手把手带你实现一个完整的家长控制应用,全程不超过5分钟(不含你测试的时间)~
一、实战案例概述
我们将实现一个功能完善的家长控制应用,包含以下核心功能:
1. 核心功能模块
| 功能模块 | 说明 |
|---|---|
| 用户授权管理 | 请求和取消用户授权,查看授权状态 |
| 守护策略管理 | 添加、修改、查询、删除、启动、停止守护策略 |
| 应用访问限制 | 设置和解除应用访问限制 |
| 策略状态监控 | 实时显示策略运行状态 |
| 数据持久化 | 保存所有配置和状态 |
2. 应用特点
- 🎯 完整的屏幕时间管控功能
- 🔐 用户授权和权限管理
- 📱 应用选择和管控
- ⏰ 多种时间策略类型支持
- 🚫 黑白名单限制模式
- 💾 数据持久化保存
- 📊 状态实时显示
二、完整实现代码
下面是一个完整的家长控制应用实现:
1. TimeGuardExtensionAbility 实现
// ets/entryability/TimeGuardExtension.ets
import { TimeGuardExtensionAbility } from '@kit.ScreenTimeGuardKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
export default class TimeGuardExtension extends TimeGuardExtensionAbility {
async onStart(strategyName: string): Promise<void> {
hilog.info(0x0000, 'TimeGuardExtension', `策略启动: ${strategyName}`);
// 在这里执行策略启动时的逻辑
// 比如发送通知、记录日志等
}
async onStop(strategyName: string): Promise<void> {
hilog.info(0x0000, 'TimeGuardExtension', `策略停止: ${strategyName}`);
// 在这里执行策略停止时的逻辑
}
async onUserAuthSwitchOn(): Promise<void> {
hilog.info(0x0000, 'TimeGuardExtension', '用户授权开启');
// 在这里执行用户授权开启时的逻辑
}
async onUserAuthSwitchOff(): Promise<void> {
hilog.info(0x0000, 'TimeGuardExtension', '用户授权关闭');
// 在这里执行用户授权关闭时的逻辑
}
}
2. 主页面实现
import { guardService, appPicker, TimeGuardExtensionAbility } 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 ParentalControlApp {
// 授权状态
@State authStatus: string = '未知';
// 守护策略相关
@State strategies: guardService.GuardStrategy[] = [];
@State selectedStrategy: guardService.GuardStrategy | null = null;
@State runningStrategies: Set<string> = new Set();
// 应用访问限制相关
@State restrictionTokens: string[] = [];
@State restrictionType: string = 'BLOCKLIST_TYPE';
@State isRestricted: boolean = false;
// Tab 导航
@State currentTab: number = 0;
// 消息提示
@State message: string = '';
// 策略表单数据
@State strategyName: string = '';
@State strategyType: string = 'START_END_TIME_TYPE';
@State startTime: string = '09:00';
@State endTime: string = '18:00';
@State duration: number = 7200;
@State repeatDays: number[] = [1, 2, 3, 4, 5];
@State strategyRestrictionType: string = 'BLOCKLIST_TYPE';
// 用户首选项
private pref: preferences.Preferences | null = null;
async aboutToAppear() {
// 初始化用户首选项
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
this.pref = await preferences.getPreferences(context, 'parental_control_data');
// 加载保存的状态
await this.loadStatus();
// 检查授权状态
await this.checkAuthStatus();
// 查询所有策略
await this.queryStrategies();
}
/**
* 加载保存的状态
*/
async loadStatus() {
try {
if (this.pref) {
const running = await this.pref.get('running_strategies', '') as string;
if (running) {
this.runningStrategies = new Set(JSON.parse(running));
}
const restricted = await this.pref.get('is_restricted', false) as boolean;
this.isRestricted = restricted;
const tokens = await this.pref.get('restriction_tokens', '') as string;
if (tokens) {
this.restrictionTokens = JSON.parse(tokens);
}
const type = await this.pref.get('restriction_type', 'BLOCKLIST_TYPE') as string;
this.restrictionType = type;
}
} catch (err) {
hilog.error(0x0000, 'ParentalControlApp', 'loadStatus failed');
}
}
/**
* 保存状态
*/
async saveStatus() {
try {
if (this.pref) {
await this.pref.put('running_strategies', JSON.stringify([...this.runningStrategies]));
await this.pref.put('is_restricted', this.isRestricted);
await this.pref.put('restriction_tokens', JSON.stringify(this.restrictionTokens));
await this.pref.put('restriction_type', this.restrictionType);
await this.pref.flush();
}
} catch (err) {
hilog.error(0x0000, 'ParentalControlApp', '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, 'ParentalControlApp',
`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, 'ParentalControlApp',
`requestUserAuth failed with error code: ${code}, message: ${message}`);
}
}
/**
* 取消用户授权
*/
async revokeAuth() {
try {
await guardService.revokeUserAuth();
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, 'ParentalControlApp',
`revokeUserAuth failed with error code: ${code}, message: ${message}`);
}
}
/**
* 查询所有策略
*/
async queryStrategies() {
try {
const strategies = await guardService.queryGuardStrategies();
this.strategies = strategies;
hilog.info(0x0000, 'ParentalControlApp',
`found ${strategies.length} strategies`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `查询失败: ${message}`;
hilog.error(0x0000, 'ParentalControlApp',
`queryGuardStrategies failed with error code: ${code}, message: ${message}`);
}
}
/**
* 添加策略
*/
async addStrategy() {
if (!this.strategyName.trim()) {
this.message = '请输入策略名称';
return;
}
if (this.restrictionTokens.length === 0) {
this.message = '请先选择要管控的应用';
return;
}
try {
const time: guardService.TimeStrategy = {
type: this.strategyType as guardService.TimeStrategyType,
startTime: this.startTime,
endTime: this.endTime,
duration: this.duration,
repeat: this.repeatDays
};
const appInfo: guardService.AppInfo = {
appTokens: this.restrictionTokens
};
const strategy: guardService.GuardStrategy = {
name: this.strategyName,
timeStrategy: time,
appInfo: appInfo,
appRestrictionType: this.strategyRestrictionType as guardService.RestrictionType
};
await guardService.addGuardStrategy(strategy);
this.message = '策略添加成功';
hilog.info(0x0000, 'ParentalControlApp',
`addGuardStrategy succeeded: ${this.strategyName}`);
// 刷新策略列表
await this.queryStrategies();
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `添加失败: ${message}`;
hilog.error(0x0000, 'ParentalControlApp',
`addGuardStrategy failed with error code: ${code}, message: ${message}`);
}
}
/**
* 删除策略
*/
async removeStrategy() {
if (!this.selectedStrategy) {
this.message = '请先选择要删除的策略';
return;
}
try {
await guardService.removeGuardStrategy(this.selectedStrategy.name);
// 从运行列表中移除
if (this.runningStrategies.has(this.selectedStrategy.name)) {
this.runningStrategies.delete(this.selectedStrategy.name);
await this.saveStatus();
}
this.message = '策略删除成功';
hilog.info(0x0000, 'ParentalControlApp',
`removeGuardStrategy succeeded: ${this.selectedStrategy.name}`);
// 刷新策略列表
await this.queryStrategies();
this.selectedStrategy = null;
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `删除失败: ${message}`;
hilog.error(0x0000, 'ParentalControlApp',
`removeGuardStrategy failed with error code: ${code}, message: ${message}`);
}
}
/**
* 启动策略
*/
async startStrategy() {
if (!this.selectedStrategy) {
this.message = '请先选择策略';
return;
}
if (this.runningStrategies.has(this.selectedStrategy.name)) {
this.message = '策略已在运行中';
return;
}
try {
await guardService.startGuardStrategy(this.selectedStrategy.name);
this.runningStrategies.add(this.selectedStrategy.name);
await this.saveStatus();
this.message = '策略启动成功';
hilog.info(0x0000, 'ParentalControlApp',
`startGuardStrategy succeeded: ${this.selectedStrategy.name}`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `启动失败: ${message}`;
hilog.error(0x0000, 'ParentalControlApp',
`startGuardStrategy failed with error code: ${code}, message: ${message}`);
}
}
/**
* 停止策略
*/
async stopStrategy() {
if (!this.selectedStrategy) {
this.message = '请先选择策略';
return;
}
if (!this.runningStrategies.has(this.selectedStrategy.name)) {
this.message = '策略未在运行中';
return;
}
try {
await guardService.stopGuardStrategy(this.selectedStrategy.name);
this.runningStrategies.delete(this.selectedStrategy.name);
await this.saveStatus();
this.message = '策略停止成功';
hilog.info(0x0000, 'ParentalControlApp',
`stopGuardStrategy succeeded: ${this.selectedStrategy.name}`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `停止失败: ${message}`;
hilog.error(0x0000, 'ParentalControlApp',
`stopGuardStrategy failed with error code: ${code}, message: ${message}`);
}
}
/**
* 选择应用
*/
async selectApps() {
try {
const tokens = await appPicker.startAppPicker(
this.getUIContext().getHostContext() as common.UIAbilityContext,
{ appTokens: this.restrictionTokens }
);
this.restrictionTokens = tokens;
this.message = `已选择 ${tokens.length} 个应用`;
hilog.info(0x0000, 'ParentalControlApp',
`selected ${tokens.length} apps`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `选择应用失败: ${message}`;
hilog.error(0x0000, 'ParentalControlApp',
`startAppPicker failed with error code: ${code}, message: ${message}`);
}
}
/**
* 设置应用访问限制
*/
async setRestriction() {
if (this.restrictionTokens.length === 0) {
this.message = '请先选择要限制的应用';
return;
}
try {
const appInfo: guardService.AppInfo = {
appTokens: this.restrictionTokens
};
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 = `应用访问限制设置成功`;
hilog.info(0x0000, 'ParentalControlApp',
`setAppsRestriction succeeded`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `设置失败: ${message}`;
hilog.error(0x0000, 'ParentalControlApp',
`setAppsRestriction failed with error code: ${code}, message: ${message}`);
}
}
/**
* 解除应用访问限制
*/
async releaseRestriction() {
if (this.restrictionTokens.length === 0) {
this.message = '请先选择要解除限制的应用';
return;
}
try {
const appInfo: guardService.AppInfo = {
appTokens: this.restrictionTokens
};
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.restrictionTokens = [];
await this.saveStatus();
this.message = `应用访问限制解除成功`;
hilog.info(0x0000, 'ParentalControlApp',
`releaseAppsRestriction succeeded`);
} catch (err) {
const message = (err as BusinessError).message;
const code = (err as BusinessError).code;
this.message = `解除失败: ${message}`;
hilog.error(0x0000, 'ParentalControlApp',
`releaseAppsRestriction failed with error code: ${code}, message: ${message}`);
}
}
/**
* 获取策略描述
*/
getStrategyDesc(strategy: guardService.GuardStrategy): string {
const time = strategy.timeStrategy;
let desc = '';
if (time.type === guardService.TimeStrategyType.START_END_TIME_TYPE) {
desc = `${time.startTime}-${time.endTime}`;
} else if (time.type === guardService.TimeStrategyType.TOTAL_DURATION_TYPE) {
desc = `总时长: ${Math.floor((time.duration || 0) / 60)} 分钟`;
} else if (time.type === guardService.TimeStrategyType.SHARED_DURATION_TYPE) {
desc = `共享时长: ${Math.floor((time.duration || 0) / 60)} 分钟`;
}
return desc;
}
build() {
Column() {
// 标题栏
Row() {
Text('家长控制应用')
.fontSize(24)
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height(60)
.backgroundColor('#007DFF')
.padding({ left: 20 })
// 消息显示
Text(this.message)
.fontSize(14)
.margin({ top: 10 })
.fontColor('#666666')
// 授权状态
Row() {
Text('授权状态: ' + this.authStatus)
.fontSize(16)
.layoutWeight(1)
if (this.authStatus === '已授权') {
Button('取消授权')
.onClick(() => this.revokeAuth())
} else {
Button('请求授权')
.onClick(() => this.requestAuth())
}
}
.margin({ top: 10 })
.width('100%')
.padding({ left: 20, right: 20 })
.backgroundColor('#F5F5F5')
.borderRadius(8)
// Tab 导航
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
this.StrategyManagementTab()
}
.tabBar('策略管理')
TabContent() {
this.AppRestrictionTab()
}
.tabBar('应用限制')
}
.barHeight(50)
.margin({ top: 20 })
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
@Builder
StrategyManagementTab() {
Column() {
// 控制按钮
Row() {
Button('刷新')
.onClick(() => this.queryStrategies())
.layoutWeight(1)
.margin({ right: 5 })
Button('启动')
.onClick(() => this.startStrategy())
.layoutWeight(1)
.margin({ left: 5, right: 5 })
Button('停止')
.onClick(() => this.stopStrategy())
.layoutWeight(1)
.margin({ left: 5 })
}
.margin({ top: 20 })
.width('90%')
// 策略列表
if (this.strategies.length > 0) {
List() {
ForEach(this.strategies, (strategy: guardService.GuardStrategy) => {
ListItem() {
Column() {
Row() {
Text(strategy.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
if (this.runningStrategies.has(strategy.name)) {
Text('运行中')
.fontSize(12)
.fontColor('#00FF00')
.backgroundColor('#E8F5E9')
.padding({ left: 8, right: 8 })
.borderRadius(4)
}
}
.width('100%')
Text(this.getStrategyDesc(strategy))
.fontSize(14)
.fontColor('#666666')
.margin({ top: 5 })
Text(`应用数量: ${strategy.appInfo.appTokens.length}`)
.fontSize(12)
.fontColor('#999999')
.margin({ top: 5 })
}
.width('100%')
.padding(15)
.backgroundColor(
this.selectedStrategy?.name === strategy.name ? '#E8F5E9' : '#F5F5F5'
)
.borderRadius(8)
.margin({ top: 5 })
.onClick(() => {
this.selectedStrategy = strategy;
})
}
})
}
.width('100%')
.height('50%')
.margin({ top: 20 })
} else {
Text('暂无策略,点击"添加策略"创建')
.fontSize(16)
.margin({ top: 30 })
.fontColor('#999999')
}
// 底部按钮
Row() {
Button('添加策略')
.onClick(() => { this.currentTab = 1; })
.layoutWeight(1)
.margin({ right: 10 })
Button('删除策略')
.onClick(() => this.removeStrategy())
.layoutWeight(1)
.margin({ left: 10 })
}
.margin({ top: 20 })
.width('90%')
}
.width('100%')
.height('100%')
.padding(20)
}
@Builder
AppRestrictionTab() {
Scroll() {
Column() {
// 限制状态
Row() {
Text('限制状态: ' + (this.isRestricted ? '已开启' : '未开启'))
.fontSize(16)
.layoutWeight(1)
if (this.isRestricted) {
Text('✓')
.fontSize(16)
.fontColor('#00FF00')
}
}
.width('100%')
.padding({ left: 20, right: 20 })
.backgroundColor('#F5F5F5')
.borderRadius(8)
.margin({ top: 20 })
// 应用选择
Text('选择要限制的应用')
.fontSize(16)
.margin({ top: 30 })
Button('选择应用')
.onClick(() => this.selectApps())
.margin({ top: 10 })
.width('90%')
Text(`已选择 ${this.restrictionTokens.length} 个应用`)
.fontSize(14)
.margin({ top: 5 })
.fontColor('#666666')
// 控制按钮
Row() {
Button('设置限制')
.onClick(() => this.setRestriction())
.layoutWeight(1)
.margin({ right: 10 })
Button('解除限制')
.onClick(() => this.releaseRestriction())
.layoutWeight(1)
.margin({ left: 10 })
}
.margin({ top: 30 })
.width('90%')
}
.width('100%')
.padding(20)
}
}
}
三、功能特点
这个完整的家长控制应用具有以下特点:
1. 完整的功能模块
- ✅ 用户授权管理
- ✅ 守护策略管理(增删改查启停)
- ✅ 应用访问限制(设置和解除)
- ✅ 策略状态监控
- ✅ 数据持久化
2. 用户体验优化
- 📱 简洁直观的界面
- 🎯 Tab 导航切换
- 💬 消息提示反馈
- 📊 状态实时显示
3. 技术亮点
- 💾 数据持久化保存
- 🔧 完整的错误处理
- 📝 详细的日志记录
- 🎨 良好的代码结构
四、使用流程
使用这个家长控制应用的完整流程:
1. 首次使用
↓
2. 请求用户授权
↓
3. 选择要管控的应用
↓
4. 添加守护策略(选择策略类型、时间规则)
↓
5. 启动策略
↓
6. 策略开始生效
↓
7. 可随时查看、修改、删除、停止策略
↓
8. 也可以设置应用访问限制
五、注意事项
🥦 西兰花警告:
- 必须先获得用户授权: 使用任何功能之前,必须先请求用户授权
- 策略名称必须唯一: 不能有同名的策略
- 限制和解除必须对称: 解除限制必须和限制的类型匹配
- 应用 Token 要保存: 应用 Token 需要保存好,用于后续操作
- 启动后系统时间锁定: 策略启动后,系统时间会被锁定
- 管控应用不可卸载: 策略启动后,管控应用会被设置为不可卸载
- 数据持久化: 所有配置和状态都会保存,重启应用后不会丢失
六、扩展建议
这个家长控制应用还可以进一步扩展:
1. 功能扩展
- 📊 使用统计和报表
- 🔔 通知和提醒功能
- 👤 多用户支持
- 📅 日历视图
- 🎮 游戏专用模式
2. UI/UX 优化
- 🎨 更美观的界面设计
- 📱 适配不同屏幕尺寸
- 🌓 支持深色模式
- 🎬 添加动画效果
- 📝 更详细的帮助文档
3. 性能优化
- ⚡ 数据加载优化
- 🔄 状态同步优化
- 💾 存储优化
- 📊 内存优化
七、文档资源
官方文档链接:
八、总结
恭喜你! 到这里,你已经学会了 Screen Time Guard Kit 的所有核心功能,并且能够独立实现一个完整的家长控制应用了~
核心要点:
- 完整的用户授权管理
- 守护策略的增删改查启停
- 应用访问限制的设置和解除
- 数据持久化保存
- 良好的用户体验设计
- 完整的错误处理
这个实战案例整合了我们前面学过的所有功能,是一个功能完善的家长控制应用。你可以直接使用这个代码,或者在此基础上进行扩展和优化~
下一步行动
建议你:
- 运行这个完整的家长控制应用
- 测试所有功能模块
- 根据实际需求进行调整和优化
- 添加更多功能(如使用统计、通知等)
- 优化 UI/UX 设计
- 发布到应用商店
记住,不教理论,只给你能跑的代码和避坑指南! _
STG 系列总结
恭喜你完成了整个 STG 系列的学习! 让我们来回顾一下这 11 篇文章的内容:
- 屏幕时间守护服务全攻略 - STG 概述和核心功能介绍
- 配置签名与权限申请 - 开发前的准备工作
- 用户授权管理详解 - 请求和取消用户授权
- 应用选择页功能详解 - 拉起应用选择页
- 守护策略管理-添加与修改策略 - 策略的创建和修改
- 守护策略管理-查询与删除策略 - 策略的查询和删除
- 守护策略管理-启动与停止策略 - 策略的启动和停止
- 守护策略管理完整实战 - 策略管理的完整示例
- 应用访问限制-设置限制 - 设置应用访问限制
- 应用访问限制-解除限制 - 解除应用访问限制
- Screen Time Guard Kit完整实战案例 - 完整的家长控制应用
通过这 11 篇文章,你已经掌握了 Screen Time Guard Kit 的所有核心功能,可以独立开发各种屏幕时间管控应用了~
我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
STG 系列完结,下个系列见!🥦
更多推荐


所有评论(0)