Harmony os——代理提醒(Reminder Agent,ArkTS)速记 & 考点整理

103 阅读7分钟

Harmony os——代理提醒(Reminder Agent,ArkTS)速记 & 考点整理

一句话记: App 退后台甚至进程杀掉了,还想准点给用户弹通知 → 用“系统代发”的代理提醒(倒计时 / 日历 / 闹钟)。


1. 它到底是干嘛的?

  • 场景: App 在后台 or 被系统终止,但你还想在指定时间提醒用户,比如:

    • 闹钟、日程提醒、喝水提醒、学习打卡、记账、经期/用药提醒
    • 行程提醒、运动训练提醒、游戏内重要事件提醒等
  • 核心特性

    • 提醒由 系统代理执行,不依赖你的进程是否存活。

    • 到点后由 Notification Kit 发通知,显示在通知中心。

    • 支持 3 种类型:

      1. 倒计时(Timer)
      2. 日历(Calendar)
      3. 闹钟(Alarm)

⚠️ 重点:这是能力比较“敏感”,有严格的管控,防止拿来做广告、营销推送。


2. 约束 & 限制(背下来)

2.1 设备限制

  • 适用设备:

    • 手机、平板、PC/2in1、智慧屏、智能穿戴设备
  • 管控差异:

    • 手机 / 平板 / PC/2in1:有管控,不能直接用,要走申请流程。
    • 智慧屏 / 智能穿戴:无管控限制。

2.2 管控限制(超关键)

如果是手机 / 平板 / PC/2in1:

  1. 没有开通能力 → 不能直接用接口

  2. 两种替代 / 解决方案:

    • Calendar Kit 做日历类提醒;
    • 或者走 “代理提醒开放能力申请” 流程,审核通过后才能调接口。
应用类型限制(必须满足)

只能是这些类别的 App 才能申请:

  • 工具类、商务类、效率类、金融理财类、教育类、生活服务类、
  • 旅游类、医疗类、运动健康类、游戏类

申请时需要提供 应用分类截图(从 AGC 后台“应用信息”里截)。

场景限制(不能是营销)
  • 营销类场景 不允许 用代理提醒,例如:

    • 抢购 / 红包 / 优惠券 / 电商促销
    • 直播预约提醒等
  • 允许的典型场景(都是“生活 / 健康 / 学习 / 办公 / 游戏重要事件”):

    • 生活:闹钟、记账、日程/纪念日、临期提醒、习惯打卡、计时等
    • 运动健康:运动、喝水、饮食记录、测血糖/吃药、睡眠、疫苗/产检等
    • 学习:课程提醒、背单词提醒、学习打卡
    • 办公:排班、考勤打卡提醒
    • 游戏:游戏内关键任务、角色生命危险、资产被攻击等

总结:应用类型 + 场景,两者都合法才能申请。只要沾“营销/拉新/促活”色彩,基本没戏。


2.3 个数限制(必背数字)

  • 单个普通 App 的有效 / 未过期提醒数 ≤ 30 个

  • 所有 App 总和(系统层面):

    • API 10 及以后:总有效提醒 ≤ 12000 个
    • API 9 及以前:总有效提醒 ≤ 2000 个

“有效/未过期”含义:

  • 到点弹出通知 但未点关闭/CLOSE → 仍视为有效。
  • 周期性提醒(每天提醒):无论用户点没点关闭 → 仍视为有效。

2.4 跳转限制 & 其他关系

  • 点击通知后,只能跳回“本应用” (即申请代理提醒的 App)。

  • 和其他 Kit 的关系:

    • 到点后实际是 Notification Kit 发通知
    • 如果自带 Calendar Kit,可以直接用日历+通知,不一定非要代理提醒。
  • 模拟器:

    • API 20 开始,模拟器也支持代理提醒调试。

3. 关键 API 总览(都是 Promise 版)

模块:

 import { reminderAgentManager } from '@kit.BackgroundTasksKit';
 import { notificationManager } from '@kit.NotificationKit';
 import { BusinessError } from '@kit.BasicServicesKit';
接口名作用
publishReminder(reminderReq)发布代理提醒,返回 reminderId: number
cancelReminder(reminderId)取消指定 ID 的代理提醒
getValidReminders()获取当前应用所有有效(未过期)的提醒列表
cancelAllReminders()取消当前应用所有代理提醒
addNotificationSlot(slot)添加通知渠道(猫眼:渠道类型、重要性等)
removeNotificationSlot(slotType)删除指定 SlotType 的通知渠道

4. 全流程开发步骤(从“不能用”到“能正常提醒”)

4.1 在 AGC 申请“代理提醒开放能力”

  1. 登录 AppGallery Connect → 选择项目 → 对应 HarmonyOS 应用。

  2. 进入: “项目设置” → “开放能力管理”

  3. 找到“代理提醒”卡片 → 点“申请”:

    • 填写申请原因(说明你是闹钟/学习/健康/办公等场景)。

    • 上传:

      • 代理提醒场景截图(比如 UI 里展示设置提醒的页面)。
      • 应用分类信息截图(从“应用上架 → 应用信息”页面截)。
  4. 提交后,按钮状态变成“申请中”(8 个工作日左右反馈)。

  5. 审核通过后:

    • 互动中心会发通知;
    • 页面按钮变为灰色“申请”,同时会出现一个 能力开关
  6. 勾选“代理提醒”开关 → 右上角保存。 ⚠️ 注意:此后 调试 & 发布必须用手动签名


4.2 申请权限

module.json5 中声明:

 "requestPermissions": [
   {
     "name": "ohos.permission.PUBLISH_AGENT_REMINDER"
   }
 ]

4.3 请求通知授权(运行时)

你的 App 要先让用户允许通知:

  • 使用 NotificationKit 的授权接口,通常在第一次使用前弹出说明,让用户同意。

4.4 编码部分:定义提醒对象 & 发布

4.4.1 倒计时型(Timer)

适合:几秒/几分钟后提醒一次——比如“小计时器、番茄钟、短期提醒”。

 let targetReminderAgent: reminderAgentManager.ReminderRequestTimer = {
   reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_TIMER, // 倒计时类型
   triggerTimeInSeconds: 10, // 从现在起 10 秒后提醒
 ​
   // 通知上的按钮
   actionButton: [
     {
       title: 'close',
       type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
     }
   ],
 ​
   // 点击通知后跳转目标
   wantAgent: {
     pkgName: 'com.example.myapplication',
     abilityName: 'EntryAbility'
   },
 ​
   title: 'this is title',                // 通知标题
   content: 'this is content',            // 通知正文
   expiredContent: 'this reminder has expired', // 过期后显示的内容(点开时)
   notificationId: 100,                   // 通知 ID,相同会覆盖
   slotType: notificationManager.SlotType.SOCIAL_COMMUNICATION // 通知渠道类型
 };

4.4.2 日历型(Calendar)

适合:具体日期 + 时间,可选“按月/按日重复”: 比如:每月 1 号 11:14:30 提醒、纪念日/账单日/学习日程。

 let targetReminderAgent: reminderAgentManager.ReminderRequestCalendar = {
   reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_CALENDAR, // 日历型
 
   // 目标时间
   dateTime: {
     year: 2023,
     month: 1,
     day: 1,
     hour: 11,
     minute: 14,
     second: 30
   },
 
   repeatMonths: [1],   // 每年 1 
   repeatDays: [1],     // 每月 1 日(注意这里按日配置)
 
   actionButton: [
     {
       title: 'close',
       type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
     },
     {
       title: 'snooze',
       type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE
     }
   ],
 
   wantAgent: {
     pkgName: 'com.example.myapplication',
     abilityName: 'EntryAbility'
   },
 
   ringDuration: 5,     // 响铃时长(秒)
   snoozeTimes: 2,      // 可延迟提醒次数
   timeInterval: 5 * 60,// 每次延迟的间隔(秒)
 
   title: 'this is title',
   content: 'this is content',
   expiredContent: 'this reminder has expired',
   snoozeContent: 'remind later', // 延迟提醒时显示的文案
 
   notificationId: 100,
   slotType: notificationManager.SlotType.SOCIAL_COMMUNICATION
 };

4.4.3 闹钟型(Alarm)

适合:指定每天/每周某些时刻: 比如:每周二 23:09 提醒。

 let targetReminderAgent: reminderAgentManager.ReminderRequestAlarm = {
   reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_ALARM, // 闹钟型
 
   hour: 23,      // 23:09 提醒
   minute: 9,
   daysOfWeek: [2], // 周二(具体数字代表周几以官方枚举为准)
 
   actionButton: [
     {
       title: 'close',
       type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE
     },
     {
       title: 'snooze',
       type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE
     }
   ],
 
   wantAgent: {
     pkgName: 'com.example.myapplication',
     abilityName: 'EntryAbility'
   },
 
   ringDuration: 5,
   snoozeTimes: 2,
   timeInterval: 5 * 60,
 
   title: 'this is title',
   content: 'this is content',
   expiredContent: 'this reminder has expired',
   snoozeContent: 'remind later',
 
   notificationId: 99,
   slotType: notificationManager.SlotType.SOCIAL_COMMUNICATION
 };

4.5 发布 / 取消代理提醒

发布
 reminderAgentManager.publishReminder(targetReminderAgent)
   .then((res: number) => {
     console.info('Succeeded in publishing reminder.');
     let reminderId: number = res; // 保存 reminderId 以便之后取消
   })
   .catch((err: BusinessError) => {
     console.error(`Failed to publish reminder. Code: ${err.code}, message: ${err.message}`);
   });
取消指定提醒
 let reminderId: number = 1; // 来自 publish 返回的 ID
 ​
 reminderAgentManager.cancelReminder(reminderId)
   .then(() => {
     console.info('Succeeded in canceling reminder.');
   })
   .catch((err: BusinessError) => {
     console.error(`Failed to cancel reminder. Code: ${err.code}, message: ${err.message}`);
   });

(如有需要,也可以用 getValidReminders() 查看当前有效提醒列表,或用 cancelAllReminders() 一次性清掉本应用的所有代理提醒。)


5. 考点 / 记忆小结

  • 定位

    • “进程死了还能提醒” → 代理提醒
    • “退后台还要持续跑逻辑” → 长时任务
    • “退后台之前临时抢几分钟时间” → 短时任务
    • “实时性不高、系统看情况帮我跑” → 延迟任务(WorkScheduler)
  • 关键数字

    • 单 App 有效提醒 ≤ 30

    • 所有 App 总有效提醒:

      • API ≥ 10:≤ 12000
      • API ≤ 9:≤ 2000
  • 两个限制维度

    1. App 类型必须在允许列表内;
    2. 场景不能是营销类(抢购/直播预约等)。
  • 三种类型

    • Timer:倒计时 N 秒后提醒
    • Calendar:具体年月日时间 + 可重复
    • Alarm:每天 / 每周固定时刻