You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native Expo每日定时通知异常排查及方案咨询

问题诊断与解决方案

核心问题分析

1. 启动后立即推送通知

你代码中使用的{hour:18, minute:0, repeats:true}重复触发器,Expo的规则是:如果当前时间已经超过设定的18:00,会立即触发一次通知,之后才会在每日18:00重复推送。比如当前是19点,设置后马上推一次,第二天18点再推。

2. 无Snooze按钮

几个关键原因:

  • 未配置前台通知显示策略:APP在前台时,Expo默认不会弹出通知弹窗,自然看不到Snooze按钮。
  • 权限请求不完整:仅配置了iOS权限,Android端权限未明确请求,导致部分功能受限。
  • Android端通知动作未适配:你的分类配置仅针对iOS,Android需要额外指定动作的安卓属性。
  • 分类注册时机可能滞后:如果通知在分类注册前被触发,会无法关联到动作按钮。

场景适配性与库选择

  • 是否适合本地通知:完全适合。每日固定时间的提醒属于本地触发场景,不需要依赖服务器推送,本地通知是最优方案。
  • 是否需要更换库:不需要。expo-notifications完全支持定时重复通知和自定义动作按钮,只需调整配置即可。

修复后的代码示例

import { useEffect } from 'react';
import * as Notifications from 'expo-notifications';

// 必须在App初始化时设置前台通知处理
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
  }),
});

const useDailyNotification = () => {
  useEffect(() => {
    const setupNotifications = async () => {
      try {
        // 1. 请求完整的权限(iOS + Android)
        const { status } = await Notifications.requestPermissionsAsync({
          ios: {
            allowAlert: true,
            allowBadge: true,
            allowSound: true,
          },
          android: {
            allowAlert: true,
            allowBadge: true,
            allowSound: true,
            allowAnnouncements: true,
          },
        });

        if (status !== 'granted') {
          console.warn('通知权限未授予');
          return;
        }

        // 2. 取消现有通知避免重复
        await Notifications.cancelAllScheduledNotificationsAsync();

        // 3. 配置通知分类(适配iOS和Android)
        await Notifications.setNotificationCategoryAsync('DAILY_REMINDER', [
          {
            identifier: 'SNOOZE_ACTION',
            buttonTitle: '稍后提醒2小时',
            options: {
              isDestructive: false,
              isAuthenticationRequired: false,
            },
            android: {
              intentIdentifier: 'SNOOZE_ACTION',
              opensAppToForeground: true,
            },
          },
        ]);

        // 4. 正确调度每日18:00的通知(避免立即触发)
        await scheduleNotification();
        console.log('每日18:00通知已成功调度');

        // 5. 监听通知响应
        const subscription = Notifications.addNotificationResponseReceivedListener(
          handleNotificationResponse
        );

        return () => subscription.remove();
      } catch (error) {
        console.error('通知设置失败:', error);
      }
    };

    setupNotifications();
  }, []);

  const handleNotificationResponse = async (response) => {
    const { actionIdentifier } = response;
    if (actionIdentifier === 'SNOOZE_ACTION') {
      await scheduleSnoozeNotification();
    }
  };

  const scheduleNotification = async () => {
    try {
      const now = new Date();
      let triggerDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 18, 0, 0);
      
      // 如果当前时间已过18:00,设置为第二天的18:00
      if (now > triggerDate) {
        triggerDate.setDate(triggerDate.getDate() + 1);
      }

      await Notifications.scheduleNotificationAsync({
        content: {
          title: '标题',
          body: '内容',
          sound: true,
          categoryIdentifier: 'DAILY_REMINDER',
        },
        trigger: {
          date: triggerDate,
          repeats: true,
        },
      });
    } catch (error) {
      console.error('调度通知失败:', error);
      throw error;
    }
  };

  const scheduleSnoozeNotification = async () => {
    try {
      const snoozeTime = new Date();
      snoozeTime.setHours(snoozeTime.getHours() + 2);

      await Notifications.scheduleNotificationAsync({
        content: {
          title: '标题(已稍后提醒)',
          body: '内容',
          sound: true,
          categoryIdentifier: 'DAILY_REMINDER',
        },
        trigger: {
          date: snoozeTime,
        },
      });

      console.log('已调度2小时后的稍后提醒通知');
    } catch (error) {
      console.error('调度稍后提醒通知失败:', error);
    }
  };
};

export default useDailyNotification;

额外注意事项

  • 测试时,建议将时间设置为当前时间几分钟后,避免等待18:00。
  • iOS模拟器上部分通知功能可能受限,建议用真机测试。
  • Android上需要确保APP在后台时,系统允许通知弹窗(部分厂商的省电模式可能会拦截)。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:48:10