You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React Native(Expo)中如何处理定时重复推送通知

基于Expo实现React Native定时重复推送通知方案

嘿,我刚好之前做过类似的需求,给你梳理一下基于Expo的实现思路,完美匹配你的需求:

先解答你的两个疑问

a) 如何监控重复事件(后台/未运行也能触发)

Expo已经帮我们封装好了系统级的通知调度能力,不需要自己写复杂的后台监控逻辑——直接用expo-notifications的调度API就可以让系统在指定时间自动触发通知,不管应用是前台、后台还是完全未运行状态。系统会接管这个定时任务,不需要你的应用一直保持活跃。

b) 本地推送还是服务器推送?

对于你这种「固定时间重复触发、内容固定」的场景,优先选本地推送

  • 优势:不需要依赖服务器,用户离线也能收到,实现更简单,完全用Expo的API就能搞定
  • 如果你后续需要动态修改通知内容或者根据服务器逻辑调整触发时间,再考虑服务器推送,但目前你的需求本地推送完全够用

具体实现步骤

1. 安装依赖

首先安装必需的Expo包:

expo install expo-notifications expo-task-manager

2. 请求通知权限

在应用初始化的时候,先请求用户的通知权限(iOS和Android都需要):

import * as Notifications from 'expo-notifications';

async function requestNotificationPermissions() {
  const { status } = await Notifications.requestPermissionsAsync({
    ios: {
      allowAlert: true,
      allowBadge: true,
      allowSound: true,
    },
    android: {
      allowAlert: true,
      allowBadge: true,
      allowSound: true,
      allowVibrate: true,
      // Android 13+需要单独申请POST_NOTIFICATIONS权限
      permissions: ['POST_NOTIFICATIONS'],
    },
  });
  
  if (status !== 'granted') {
    alert('需要开启通知权限才能接收提醒');
  }
}

// 在组件挂载时调用
useEffect(() => {
  requestNotificationPermissions();
}, []);

3. 调度每日重复通知

scheduleNotificationAsync方法设置每天12:00的重复提醒,关键是设置trigger里的hourminuterepeatInterval

async function scheduleDailyReminder() {
  // 先取消已有的同类型通知(避免重复调度)
  const scheduledNotifications = await Notifications.getAllScheduledNotificationsAsync();
  for (const notification of scheduledNotifications) {
    if (notification.content.body.includes('完成任务X')) {
      await Notifications.cancelScheduledNotificationAsync(notification.identifier);
    }
  }

  // 调度新的每日通知
  const notificationId = await Notifications.scheduleNotificationAsync({
    content: {
      title: '任务提醒',
      body: '该完成任务X啦!',
      sound: true, // 开启提醒音
      badge: 1, // 图标角标(iOS适用)
    },
    trigger: {
      hour: 12, // 24小时制,12代表中午12点
      minute: 0,
      repeatInterval: 'day', // 重复间隔:每天
    },
  });
  
  console.log('每日提醒已调度,ID:', notificationId);
}

4. 处理通知点击(可选)

如果需要用户点击通知后跳转到应用内的特定页面,可以添加监听:

useEffect(() => {
  const responseListener = Notifications.addNotificationResponseReceivedListener(response => {
    // 这里可以处理路由跳转,比如导航到任务页面
    console.log('用户点击了通知:', response);
    // navigation.navigate('TaskXScreen');
  });

  return () => {
    Notifications.removeNotificationSubscription(responseListener);
  };
}, []);

5. 取消通知(用户关闭提醒时)

当用户不需要提醒时,调用取消方法:

async function cancelDailyReminder() {
  const scheduledNotifications = await Notifications.getAllScheduledNotificationsAsync();
  for (const notification of scheduledNotifications) {
    if (notification.content.body.includes('完成任务X')) {
      await Notifications.cancelScheduledNotificationAsync(notification.identifier);
    }
  }
  console.log('每日提醒已取消');
}

注意事项

  • iOS限制:如果用户手动关闭了应用的通知权限,或者系统开启了「专注模式」,通知可能会被拦截,需要引导用户开启权限
  • Android Doze模式:在Android的Doze模式下,系统会延迟非紧急通知,但Expo的通知会标记为重要通知(默认),大部分情况下会按时触发
  • 时区问题trigger里的时间是基于设备的本地时区,不需要额外处理时区转换

内容的提问来源于stack exchange,提问作者ch1maera

火山引擎 最新活动