HarmonyOS应用开发实战:猫猫大作战-ReminderRequest 的使用

HarmonyOS应用开发实战:猫猫大作战-ReminderRequest 的使用

前言

ReminderRequest是 HarmonyOS 的提醒服务能力,支持创建定时提醒、日历提醒和倒计时提醒。在「猫猫大作战」中,我们可以通过提醒功能让玩家每天定时回来领取签到奖励、通知活动开始、或者在体力回满时收到提醒。

workScheduler后台任务不同,ReminderRequest 的提醒会在系统通知栏以“实况通知“形式显示,用户可以看到醒目的提醒卡片,点击后跳转到游戏。

本文以「猫猫大作战」的每日游戏提醒为锚点,讲解 ReminderRequest 的完整使用方法。

提示:本系列不讲 ArkTS 基础语法与环境搭建。本篇是阶段五第 164 篇。

一、ReminderRequest 基础

1.1 三种提醒类型

import { reminderAgent } from '@kit.ReminderKit'; // 类型 1:定时提醒(每日固定时间) const alarmReminder: reminderAgent.ReminderRequestAlarm = { reminderType: reminderAgent.ReminderType.REMINDER_TYPE_ALARM, hour: 20, minute: 0, daysOfWeek: [1, 2, 3, 4, 5, 6, 7], // 每天 title: '猫猫大作战', content: '猫咪们等你回来合并呢!', notificationId: 2001, wantAgent: { /* 点击跳转 */ }, }; // 类型 2:日历提醒(指定日期) const calendarReminder: reminderAgent.ReminderRequestCalendar = { reminderType: reminderAgent.ReminderType.REMINDER_TYPE_CALENDAR, dateTime: { year: 2026, month: 8, day: 1, hour: 10, minute: 0 }, title: '夏日活动开启', content: '双倍积分活动开始了!', notificationId: 2002, }; // 类型 3:倒计时提醒(多久之后) const countdownReminder: reminderAgent.ReminderRequestTimer = { reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER, triggerTimeInSeconds: 3600, // 1 小时后 title: '体力恢复提醒', content: '体力已回满,继续游戏吧!', notificationId: 2003, };
类型枚举值用途触发方式
AlarmREMINDER_TYPE_ALARM每日定时提醒hour+minute+daysOfWeek
CalendarREMINDER_TYPE_CALENDAR指定日期提醒dateTime对象
TimerREMINDER_TYPE_TIMER倒计时提醒triggerTimeInSeconds

提示:notificationId必须唯一,用于更新或取消提醒。建议使用模块前缀区分不同提醒类型(如 2xxx 段)。

二、创建提醒

2.1 每日定时提醒

async function createDailyReminder(context: Context): Promise<number> { const reminder: reminderAgent.ReminderRequestAlarm = { reminderType: reminderAgent.ReminderType.REMINDER_TYPE_ALARM, hour: 20, minute: 0, daysOfWeek: [1, 2, 3, 4, 5, 6, 7], // 每天 title: '🐱 猫猫大作战', content: '猫咪们等你回来合并呢!快来领取每日奖励!', notificationId: 2001, wantAgent: { pkgName: 'com.maomaodazuozhan.game', abilityName: 'EntryAbility', // 附加参数,可在 EntryAbility 中读取 parameters: { action: 'daily_reminder' }, }, maxScreenWantAgent: { pkgName: 'com.maomaodazuozhan.game', abilityName: 'EntryAbility', }, expiredContent: '今日提醒已过期', snoozeTimes: 2, // 最多推迟 2 次 timeInterval: 10, // 每 10 分钟推迟一次 }; const reminderId = await reminderAgent.publishReminder(reminder); console.info(`每日提醒已创建,ID: ${reminderId}`); return reminderId; }

2.2 参数详解

参数类型说明示例值
hournumber提醒小时 (0-23)20
minutenumber提醒分钟 (0-59)0
daysOfWeeknumber[]每周天数 (1=周日, 2=周一…)[1,2,3,4,5,6,7]
titlestring提醒标题(显示在通知栏)‘猫猫大作战’
contentstring提醒内容‘来合并猫咪吧!’
notificationIdnumber唯一 ID,用于更新/取消2001
wantAgentobject点击提醒后的跳转配置{ pkgName, abilityName }
snoozeTimesnumber推迟次数上限2
timeIntervalnumber推迟间隔(分钟)10

三、点击提醒跳转

3.1 WantAgent 配置

// 点击提醒后跳转到游戏并自动进入活动页面 const wantAgent: reminderAgent.WantAgent = { pkgName: 'com.maomaodazuozhan.game', abilityName: 'EntryAbility', parameters: { action: 'open_activity', activityId: 'summer_2026', from: 'reminder', }, };

3.2 在 EntryAbility 中接收

// 来源:entry/src/main/ets/entryability/EntryAbility.ets import { UIAbility, Want } from '@kit.AbilityKit'; export default class EntryAbility extends UIAbility { onNewWant(want: Want): void { // 处理从提醒点击传入的参数 const action = want.parameters?.action as string; const from = want.parameters?.from as string; if (from === 'reminder') { switch (action) { case 'daily_reminder': // 打开签到页面 this.openSignInPage(); break; case 'open_activity': // 打开活动页面 const activityId = want.parameters?.activityId as string; this.openActivityPage(activityId); break; } } } private openSignInPage(): void { // 路由到签到页 console.info('从提醒跳转到签到页'); } private openActivityPage(id: string): void { console.info(`从提醒跳转到活动页: ${id}`); } }

四、提醒的增删改查

4.1 取消提醒

async function cancelReminder(reminderId: number): Promise<void> { try { await reminderAgent.cancelReminder(reminderId); console.info(`提醒 ${reminderId} 已取消`); } catch (err) { console.error(`取消提醒失败: ${err.message}`); } } // 取消所有提醒 async function cancelAllReminders(context: Context): Promise<void> { const reminders = await reminderAgent.queryReminders(context); for (const r of reminders) { await reminderAgent.cancelReminder(r.reminderId); } console.info(`已取消 ${reminders.length} 个提醒`); }

4.2 查询提醒

async function listAllReminders(context: Context): Promise<void> { const reminders = await reminderAgent.queryReminders(context); console.info(`当前有 ${reminders.length} 个活跃提醒:`); for (const r of reminders) { console.info( ` ID=${r.reminderId}, type=${r.reminderType}, ` + `title=${r.title}, content=${r.content}` ); } } async function getReminderById(reminderId: number): Promise<reminderAgent.ReminderRequest | null> { try { const reminders = await reminderAgent.queryReminders(getContext() as Context); return reminders.find(r => r.reminderId === reminderId) ?? null; } catch { return null; } }
操作API参数说明
创建publishReminder(reminder)Reminder 对象返回 reminderId
取消cancelReminder(id)提醒 ID取消单个提醒
查询queryReminders(context)Context返回所有提醒列表
更新先取消再创建原 ID 失效Reminder 不支持直接修改

五、游戏中的应用场景

5.1 每日签到提醒

async function setupSignInReminder(context: Context): Promise<void> { // 用户设置提醒时间(从 Preferences 读取) const prefs = await preferences.getPreferences(context, 'game_prefs'); const reminderHour = prefs.get('reminder_hour', 20) as number; const reminderMinute = prefs.get('reminder_minute', 0) as number; const reminder: reminderAgent.ReminderRequestAlarm = { reminderType: reminderAgent.ReminderType.REMINDER_TYPE_ALARM, hour: reminderHour, minute: reminderMinute, daysOfWeek: [1, 2, 3, 4, 5, 6, 7], title: '🐱 猫猫大作战 - 每日签到', content: '签到领取免费猫咪和金币!', notificationId: 2001, wantAgent: { pkgName: 'com.maomaodazuozhan.game', abilityName: 'EntryAbility', parameters: { action: 'sign_in' }, }, }; await reminderAgent.publishReminder(reminder); }

5.2 活动开始提醒

async function createEventReminder( context: Context, eventDate: Date, eventName: string ): Promise<number> { const reminder: reminderAgent.ReminderRequestCalendar = { reminderType: reminderAgent.ReminderType.REMINDER_TYPE_CALENDAR, dateTime: { year: eventDate.getFullYear(), month: eventDate.getMonth() + 1, day: eventDate.getDate(), hour: eventDate.getHours(), minute: eventDate.getMinutes(), }, title: `🎉 ${eventName}`, content: '限时活动已开始,登录领取奖励!', notificationId: 3001, wantAgent: { pkgName: 'com.maomaodazuozhan.game', abilityName: 'EntryAbility', parameters: { action: 'open_event' }, }, }; return await reminderAgent.publishReminder(reminder); }

5.3 体力恢复提醒(倒计时)

async function createEnergyReminder(context: Context): Promise<number> { // 假设体力每 30 分钟恢复 1 点,满 5 点需要 2.5 小时 const ENERGY_FULL_TIME = 150; // 分钟 const seconds = ENERGY_FULL_TIME * 60; const reminder: reminderAgent.ReminderRequestTimer = { reminderType: reminderAgent.ReminderType.REMINDER_TYPE_TIMER, triggerTimeInSeconds: seconds, title: '⚡ 体力恢复', content: '体力已回满,继续挑战高分吧!', notificationId: 3002, wantAgent: { pkgName: 'com.maomaodazuozhan.game', abilityName: 'EntryAbility', parameters: { action: 'open_game' }, }, }; return await reminderAgent.publishReminder(reminder); }

六、提醒样式

6.1 系统通知样式

// ReminderRequest 在系统通知栏显示为"实况通知"样式 // 包含:应用图标、标题、内容、时间、点击跳转提示 // 提醒显示效果 ┌─────────────────────────────────┐ │ 🐱 猫猫大作战 │ │ ─────────────────────── │ │ 猫咪们等你回来合并呢! │ │ 20:00 │ │ [推迟] [确定] │ └─────────────────────────────────┘

6.2 自定义参数

const reminder: reminderAgent.ReminderRequestAlarm = { // ... 基础参数 // 提醒内容在锁屏上的展示策略 maxScreenWantAgent: { pkgName: 'com.maomaodazuozhan.game', abilityName: 'EntryAbility', }, // 过期内容(提醒触发后未操作时显示) expiredContent: '今日提醒已过期,点击查看活动详情', // 推迟行为 snoozeTimes: 2, // 最多推迟 2 次 timeInterval: 10, // 每次推迟间隔 10 分钟 };

七、权限与限制

7.1 权限声明

// module.json5 中声明 { module: { requestPermissions: [ { name: 'ohos.permission.PUBLISH_AGENT_REMINDER', reason: '$string:reminder_permission_reason', }, ], }, }

7.2 运行时权限

async function ensureReminderPermission(context: Context): Promise<boolean> { const atManager = abilityAccessCtrl.createAtManager(); try { const result = await atManager.requestPermissionsFromUser(context, [ 'ohos.permission.PUBLISH_AGENT_REMINDER', ]); return result.authResults[0] === 0; } catch (err) { console.error(`提醒权限获取失败: ${err.message}`); return false; } }

7.3 限制

限制项说明
最大提醒数单应用最多 50 个活跃提醒
最小倒计时triggerTimeInSeconds >= 60(至少 1 分钟)
重复间隔repeatCycleTime >= 60 * 60 * 1000(至少 1 小时)
权限必须声明PUBLISH_AGENT_REMINDER
实况通知仅 Alarm 和 Calendar 类型支持

提示:提醒数量建议控制在 10 个以内,过多会影响系统性能和用户体验。

八、调试与测试

// 在模拟器中测试提醒 // 1. 创建提醒后等待触发 // 2. 使用 hdc 修改系统时间加速测试 // hdc shell date -s "2026-07-28 19:59:50" // 3. 等待 10 秒触发提醒 // 代码内验证提醒是否生效 async function verifyReminderCreated(context: Context): Promise<boolean> { const reminders = await reminderAgent.queryReminders(context); const targetReminder = reminders.find(r => r.title.includes('猫猫大作战')); if (targetReminder) { console.info(`提醒已生效: ID=${targetReminder.reminderId}`); return true; } console.warn('未找到提醒,请检查创建逻辑'); return false; }

九、常见问题

问题原因解决方法
提醒未触发权限未授予检查 PUBLISH_AGENT_REMINDER 权限
点击提醒未跳转WantAgent 配置错误检查 pkgName 和 abilityName
提醒多次触发重复创建未清理创建前先取消旧提醒
倒计时不准系统休眠限制使用 Alarm 定时间而非 Timer
推送栏不显示notificationId 冲突使用唯一 ID

十、最佳实践

  1. 提醒数量精简:最多 3-5 个活跃提醒,避免骚扰用户
  2. 提供推迟功能:设置snoozeTimestimeInterval给用户灵活性
  3. 跳转带参数:在parameters中传 action,区分不同场景
  4. 用户可配置:让用户可以设置提醒时间和类型
  5. 销毁时清理:应用卸载或用户退出时取消所有提醒
  6. 测试覆盖:每种提醒类型至少测试一次触发和跳转
// 用户设置提醒偏好 async function updateReminderSettings( context: Context, enabled: boolean, hour?: number, minute?: number ): Promise<void> { // 先取消所有旧提醒 const reminders = await reminderAgent.queryReminders(context); for (const r of reminders) { await reminderAgent.cancelReminder(r.reminderId); } if (enabled && hour !== undefined && minute !== undefined) { // 创建新提醒 await createDailyReminder(context); console.info(`提醒已更新: ${hour}:${minute}`); } else { console.info('提醒已关闭'); } }

总结

ReminderRequest 提供三种提醒类型——定时、日历、倒计时,适用于游戏中的每日签到提醒、活动通知和体力恢复提醒。核心要点:Alarm 定时每日提醒、 Calendar 指定日期活动、 Timer 倒计时提醒、 WantAgent 点击跳转带参数、 snoozeTimes 推迟机制、 notificationId 唯一标识

下一篇将深入 LiveViewKit——实况窗与锁屏得分展示。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

  • ReminderAgent API 参考
  • ReminderRequest 官方指南
  • WantAgent 跳转配置
  • 通知栏与提醒最佳实践
  • BACKGROUNDTASKS_KIT 权限
  • 定时提醒设计规范
  • 开源鸿蒙跨平台社区
  • HarmonyOS 开发者官方文档
  • 第 163 篇:workScheduler
  • 第 165 篇:LiveViewKit