鸿蒙学习实战之路-STG系列(7/11)-守护策略管理-启动与停止策略

朋友们,前几篇我们学习了如何添加、修改、查询和删除守护策略。今天这篇我们就来学习最关键的功能 - 启动和停止策略 o(╯□╰)o

启动策略就像"开始执行家规",停止策略就像"暂停执行家规"。只有启动了策略,管控才会真正生效~

今天这篇,我会手把手带你实现守护策略的启动和停止功能,全程不超过5分钟(不含你测试的时间)~


一、启动守护策略

启动守护策略就像"开始执行家规",策略启动后,系统就会按照规则进行管控。

1. 业务流程

启动守护策略的流程就像这样:

应用调用启动策略接口
    ↓
系统检查应用是否有权限、用户是否授权
    ↓
如果没有权限 → 抛出错误码
如果有权限 → 解析策略名称
    ↓
检查策略是否存在
    ↓
如果策略不存在 → 抛出错误码
如果策略存在 → 检查是否正在执行
    ↓
如果正在执行 → 抛出"策略已在执行中"错误
如果未执行 → 启动策略,记录启动状态
    ↓
系统时间设置为不可修改
管控应用设置为不可卸载
    ↓
策略启动成功
    ↓
到了管控生效时间,拉起 extension 进程
执行 onStart 回调

🥦 西兰花警告:
策略启动后,系统时间会被锁定,不能修改。这是为了防止用户通过修改系统时间来绕过管控,这个限制也合理吧? o(╯□╰)o

2. 核心接口

启动策略的接口:

接口名 说明
startGuardStrategy(strategyName) 根据策略名称启动管控策略
onStart(strategyName) 在策略启动时执行特定逻辑(回调)

3. 开发步骤

步骤 1: 导入相关模块
import { guardService, TimeGuardExtensionAbility } from '@kit.ScreenTimeGuardKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
步骤 2: 实现 TimeGuardExtensionAbility 回调
// ets/entryability/TimeGuardExtension.ets
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}`);
    // 在这里执行策略停止时的逻辑
  }
}
步骤 3: 启动策略
@Entry
@Component
struct StartStrategyDemo {
  @State strategyName: string = '';
  @State message: string = '';

  build() {
    Column() {
      Text('启动守护策略演示')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 40 })

      TextInput({ placeholder: '请输入策略名称' })
        .onChange((value: string) => {
          this.strategyName = value;
        })
        .margin({ top: 30 })
        .width('80%')

      Text(this.message)
        .fontSize(14)
        .margin({ top: 10 })
        .fontColor('#666666')

      Button('启动策略')
        .onClick(async () => {
          if (!this.strategyName) {
            this.message = '请输入策略名称';
            return;
          }

          try {
            await guardService.startGuardStrategy(this.strategyName);
            this.message = `策略启动成功: ${this.strategyName}`;
            hilog.info(0x0000, 'StartStrategyDemo', 
              `startGuardStrategy succeeded: ${this.strategyName}`);
          } catch (err) {
            const message = (err as BusinessError).message;
            const code = (err as BusinessError).code;
            this.message = `启动失败: ${message}`;
            hilog.error(0x0000, 'StartStrategyDemo',
              `startGuardStrategy failed with error code: ${code}, message: ${message}`);
          }
        })
        .margin({ top: 20 })
        .width('80%')
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

🥦 西兰花小贴士:
onStart 回调会在策略生效时触发,不是在调用 startGuardStrategy 时触发。比如策略是 9:00-18:00 生效,那么 onStart 会在 9:00 时触发~


二、停止守护策略

停止守护策略就像"暂停执行家规",策略停止后,系统不再按照规则进行管控。

1. 业务流程

停止守护策略的流程就像这样:

应用调用停止策略接口
    ↓
系统检查应用是否有权限、用户是否授权
    ↓
如果没有权限 → 抛出错误码
如果有权限 → 解析策略名称
    ↓
检查策略是否存在
    ↓
如果策略不存在 → 抛出错误码
如果策略存在 → 检查是否正在执行
    ↓
如果未执行 → 抛出"策略未在执行中"错误
如果正在执行 → 停止策略,记录停止状态
    ↓
策略生效期间停止 → 拉起 extension 进程
执行 onStop 回调
非策略生效期间停止 → 不触发回调
    ↓
如果该应用没有其他启动状态的策略 → 应用设置为可卸载
如果设备中没有启动状态的策略 → 系统时间设置为可修改
    ↓
策略停止成功

🥦 西兰花小贴士:
停止策略后,如果设备中没有任何启动状态的策略,系统时间就会恢复可修改状态。这个设计很人性化~

2. 核心接口

停止策略的接口:

接口名 说明
stopGuardStrategy(strategyName) 根据策略名称停止管控策略
onStop(strategyName) 在策略停止时执行特定逻辑(回调)

3. 开发步骤

@Entry
@Component
struct StopStrategyDemo {
  @State strategyName: string = '';
  @State message: string = '';

  build() {
    Column() {
      Text('停止守护策略演示')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 40 })

      TextInput({ placeholder: '请输入策略名称' })
        .onChange((value: string) => {
          this.strategyName = value;
        })
        .margin({ top: 30 })
        .width('80%')

      Text(this.message)
        .fontSize(14)
        .margin({ top: 10 })
        .fontColor('#666666')

      Button('停止策略')
        .onClick(async () => {
          if (!this.strategyName) {
            this.message = '请输入策略名称';
            return;
          }

          try {
            await guardService.stopGuardStrategy(this.strategyName);
            this.message = `策略停止成功: ${this.strategyName}`;
            hilog.info(0x0000, 'StopStrategyDemo', 
              `stopGuardStrategy succeeded: ${this.strategyName}`);
          } catch (err) {
            const message = (err as BusinessError).message;
            const code = (err as BusinessError).code;
            this.message = `停止失败: ${message}`;
            hilog.error(0x0000, 'StopStrategyDemo',
              `stopGuardStrategy failed with error code: ${code}, message: ${message}`);
          }
        })
        .margin({ top: 20 })
        .width('80%')
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

三、完整示例代码

下面是一个完整的示例,展示了如何实现守护策略的启动和停止功能:

import { guardService, TimeGuardExtensionAbility } from '@kit.ScreenTimeGuardKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { preferences } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct StrategyControlDemo {
  @State strategies: guardService.GuardStrategy[] = [];
  @State selectedStrategy: string = '';
  @State message: string = '';
  @State runningStrategies: Set<string> = new Set();
  private pref: preferences.Preferences | null = null;

  async aboutToAppear() {
    // 初始化用户首选项
    let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    this.pref = await preferences.getPreferences(context, 'strategy_control_data');

    // 加载正在运行的策略
    await this.loadRunningStrategies();

    // 查询所有策略
    await this.queryStrategies();
  }

  async loadRunningStrategies() {
    try {
      if (this.pref) {
        const running = await this.pref.get('running_strategies', '') as string;
        if (running) {
          this.runningStrategies = new Set(JSON.parse(running));
        }
      }
    } catch (err) {
      hilog.error(0x0000, 'StrategyControlDemo', 'loadRunningStrategies failed');
    }
  }

  async saveRunningStrategies() {
    try {
      if (this.pref) {
        await this.pref.put('running_strategies', JSON.stringify([...this.runningStrategies]));
        await this.pref.flush();
      }
    } catch (err) {
      hilog.error(0x0000, 'StrategyControlDemo', 'saveRunningStrategies failed');
    }
  }

  async queryStrategies() {
    try {
      const strategies = await guardService.queryGuardStrategies();
      this.strategies = strategies;
      hilog.info(0x0000, 'StrategyControlDemo', 
        `found ${strategies.length} strategies`);
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `查询失败: ${message}`;
      hilog.error(0x0000, 'StrategyControlDemo',
        `queryGuardStrategies failed with error code: ${code}, message: ${message}`);
    }
  }

  async startStrategy() {
    if (!this.selectedStrategy) {
      this.message = '请先选择策略';
      return;
    }

    if (this.runningStrategies.has(this.selectedStrategy)) {
      this.message = '策略已在运行中';
      return;
    }

    try {
      await guardService.startGuardStrategy(this.selectedStrategy);
      this.runningStrategies.add(this.selectedStrategy);
      await this.saveRunningStrategies();
      this.message = `策略启动成功: ${this.selectedStrategy}`;
      hilog.info(0x0000, 'StrategyControlDemo', 
        `startGuardStrategy succeeded: ${this.selectedStrategy}`);
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `启动失败: ${message}`;
      hilog.error(0x0000, 'StrategyControlDemo',
        `startGuardStrategy failed with error code: ${code}, message: ${message}`);
    }
  }

  async stopStrategy() {
    if (!this.selectedStrategy) {
      this.message = '请先选择策略';
      return;
    }

    if (!this.runningStrategies.has(this.selectedStrategy)) {
      this.message = '策略未在运行中';
      return;
    }

    try {
      await guardService.stopGuardStrategy(this.selectedStrategy);
      this.runningStrategies.delete(this.selectedStrategy);
      await this.saveRunningStrategies();
      this.message = `策略停止成功: ${this.selectedStrategy}`;
      hilog.info(0x0000, 'StrategyControlDemo', 
        `stopGuardStrategy succeeded: ${this.selectedStrategy}`);
    } catch (err) {
      const message = (err as BusinessError).message;
      const code = (err as BusinessError).code;
      this.message = `停止失败: ${message}`;
      hilog.error(0x0000, 'StrategyControlDemo',
        `stopGuardStrategy 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() {
      Text('守护策略控制')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 40 })

      Text(this.message)
        .fontSize(14)
        .margin({ top: 20 })
        .fontColor('#666666')

      // 策略列表
      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.selectedStrategy === strategy.name) {
                    Text('✓')
                      .fontSize(16)
                      .fontColor('#00FF00')
                  }
                }
                .width('100%')

                Row() {
                  Text(this.getStrategyDesc(strategy))
                    .fontSize(14)
                    .fontColor('#666666')
                    .layoutWeight(1)

                  if (this.runningStrategies.has(strategy.name)) {
                    Text('运行中')
                      .fontSize(12)
                      .fontColor('#00FF00')
                      .backgroundColor('#E8F5E9')
                      .padding({ left: 8, right: 8 })
                      .borderRadius(4)
                  } else {
                    Text('未运行')
                      .fontSize(12)
                      .fontColor('#999999')
                      .backgroundColor('#F5F5F5')
                      .padding({ left: 8, right: 8 })
                      .borderRadius(4)
                  }
                }
                .width('100%')
                .margin({ top: 5 })
              }
              .width('100%')
              .padding(15)
              .backgroundColor(
                this.selectedStrategy === strategy.name ? '#E8F5E9' : '#F5F5F5'
              )
              .borderRadius(8)
              .margin({ top: 5 })
              .onClick(() => {
                this.selectedStrategy = strategy.name;
              })
            }
          })
        }
        .width('100%')
        .height('40%')
        .margin({ top: 20 })
      } else {
        Text('暂无策略')
          .fontSize(16)
          .margin({ top: 30 })
          .fontColor('#999999')
      }

      // 控制按钮
      Row() {
        Button('刷新')
          .onClick(() => this.queryStrategies())
          .layoutWeight(1)
          .margin({ right: 10 })

        Button('启动')
          .onClick(() => this.startStrategy())
          .layoutWeight(1)
          .margin({ left: 10, right: 10 })

        Button('停止')
          .onClick(() => this.stopStrategy())
          .layoutWeight(1)
          .margin({ left: 10 })
      }
      .margin({ top: 20 })
      .width('80%')
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

四、注意事项

🥦 西兰花警告:

  1. 必须先获得用户授权: 启动和停止策略之前,必须先请求用户授权,否则会报错
  2. 策略名称要准确: 启动和停止策略时,策略名称必须准确,否则会抛出错误
  3. 启动后系统时间锁定: 策略启动后,系统时间会被锁定,不能修改
  4. 管控应用不可卸载: 策略启动后,管控应用会被设置为不可卸载
  5. 停止时机很重要: 在策略生效期间停止会触发 onStop 回调,非生效期间不会触发
  6. 不能重复启动: 如果策略已经在运行,重复启动会抛出错误
  7. 不能停止未运行的策略: 如果策略未在运行,停止会抛出错误

五、文档资源

官方文档链接:


六、总结

启动和停止守护策略是策略管理的关键功能,只有启动了策略,管控才会真正生效。

核心要点:

  1. 启动策略后,系统时间会被锁定,不能修改
  2. 启动策略后,管控应用会被设置为不可卸载
  3. onStart 回调在策略生效时触发,不是在启动时触发
  4. 停止策略会触发 onStop 回调(如果在策略生效期间)
  5. 如果没有启动状态的策略,系统时间会恢复可修改
  6. 不能重复启动或停止未运行的策略

启动策略就像"开始执行家规",停止策略就像"暂停执行家规"。只有启动了,管控才会真正生效 _


下一步行动

建议你:

  1. 先实现 TimeGuardExtensionAbility 的回调方法
  2. 实现策略启动功能
  3. 实现策略停止功能
  4. 添加策略状态显示(运行中/未运行)
  5. 结合查询功能,实现完整的策略控制页面

记住,不教理论,只给你能跑的代码和避坑指南! _


我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐