文章配图: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

十、最佳实践

  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——实况窗与锁屏得分展示。

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


相关资源:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐