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,
};
| 类型 | 枚举值 | 用途 | 触发方式 |
|---|---|---|---|
Alarm |
REMINDER_TYPE_ALARM |
每日定时提醒 | hour + minute + daysOfWeek |
Calendar |
REMINDER_TYPE_CALENDAR |
指定日期提醒 | dateTime 对象 |
Timer |
REMINDER_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 参数详解
| 参数 | 类型 | 说明 | 示例值 |
|---|---|---|---|
hour |
number | 提醒小时 (0-23) | 20 |
minute |
number | 提醒分钟 (0-59) | 0 |
daysOfWeek |
number[] | 每周天数 (1=周日, 2=周一…) | [1,2,3,4,5,6,7] |
title |
string | 提醒标题(显示在通知栏) | ‘猫猫大作战’ |
content |
string | 提醒内容 | ‘来合并猫咪吧!’ |
notificationId |
number | 唯一 ID,用于更新/取消 | 2001 |
wantAgent |
object | 点击提醒后的跳转配置 | { pkgName, abilityName } |
snoozeTimes |
number | 推迟次数上限 | 2 |
timeInterval |
number | 推迟间隔(分钟) | 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 |
十、最佳实践
- 提醒数量精简:最多 3-5 个活跃提醒,避免骚扰用户
- 提供推迟功能:设置
snoozeTimes和timeInterval给用户灵活性 - 跳转带参数:在
parameters中传 action,区分不同场景 - 用户可配置:让用户可以设置提醒时间和类型
- 销毁时清理:应用卸载或用户退出时取消所有提醒
- 测试覆盖:每种提醒类型至少测试一次触发和跳转
// 用户设置提醒偏好
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——实况窗与锁屏得分展示。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐



所有评论(0)