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

React Native集成Expo本地通知无推送问题求助

Expo Notifications本地推送无响应问题排查与修复

问题概述

尝试在React Native中通过Expo Notifications实现APP在前台、后台及关闭状态下接收本地推送,设置02:00为开始时间、03:30为结束时间,计划推送240次,代码运行无报错但始终收不到通知,相关代码如下:

import React, { useEffect, useState } from 'react';
import { View, Text } from 'react-native';
import * as Notifications from 'expo-notifications';

const NotificationScheduler = () => {
  const startTime = new Date();
  // Start time: 02:00 adjust, (hour, min, 0, 0)
  startTime.setHours(2, 0, 0, 0); 
  const endTime = new Date();
  // End time: 03:30 adjust, (hour, min, 0, 0)
  endTime.setHours(3, 30, 0, 0); 
  // Number of notifications, How many times you want to get notification.. 
  // ATTH; Higher number is just to get them more frequently while testing.
  const notificationCount = 240; 
  // This is just to get the message displayed on the screen if any, if it does, and no notification
  // is displayed, then something is working but not as it should.
  const [notificationMessage, setNotificationMessage] = useState('No notifications yet.');
  // Getting the difference on time, to calculate the frequent interval on the time. 
  const timeDifference = endTime.getTime() - startTime.getTime();
  // Making the interval.
  const interval = Math.max(1, Math.round(timeDifference / notificationCount));

  useEffect(() => {
    // Ensure I have permission to send notifiactions
    const requestPermissions = async () => {
      const { status } = await Notifications.requestPermissionsAsync();
      if (status !== 'granted') {
        // if not please go to settings and allow them
        alert('Please go to settings and allow notifications!');
        return;
      }
    };

    requestPermissions();

    // The scheduler for notification.
const scheduleNotifications = async () => {
  const currentDate = new Date();
  console.log('------ Starts  ------')
  for (let i = 1; i < notificationCount; i++) {
    // making the trigger for sending notifications on spesific time and sqedule them.
    const trigger = new Date(startTime.getTime() + i * interval);
    console.log('trigger : ' + trigger);
    // Setting up the notififactions
    await Notifications.scheduleNotificationAsync({
      content: {
        title: "Time to check!",
        body:`This is notification number ${i + 1}.`,
        data: { data: 'data goes here'},
      },
      trigger: {
        ...trigger,
        repeats: true,
      },
    });
  }
};

const notificationListener = Notifications.addNotificationReceivedListener(notification => {
  setNotificationMessage(notification.request.content.body);
});

const foregroundNotificationListener = Notifications.addNotificationResponseReceivedListener(response => {
  setNotificationMessage(response.notification.request.content.body);
});

scheduleNotifications();

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

return (
<View>
  <Text>Notifications scheduled!</Text>
  <Text>Latest Notification: {notificationMessage}</Text>
</View>
);
};

export default NotificationScheduler;

核心问题与修复方案

1. 触发器配置错误

你直接展开Date对象作为触发器,同时设置repeats: true是错误用法。Expo Notifications的日期触发器需要通过date字段指定时间,且你的场景是一次性批量推送,不需要开启重复推送,否则会导致触发器失效。

2. 权限请求异步处理不严谨

requestPermissions是异步函数,但你未等待权限获取完成就执行调度逻辑,可能导致权限未授予时通知调度失败。

3. 前台通知未配置默认显示

默认情况下,Expo Notifications在前台不会弹出通知,需要手动配置通知处理器允许前台显示。

4. 过期时间处理缺失

如果当前时间已超过03:30,计算出的触发时间会是当天已过去的时间,Expo会忽略这类过期触发器,需要自动调整到次日对应时间。

修复后的完整代码

import React, { useEffect, useState } from 'react';
import { View, Text, Alert } from 'react-native';
import * as Notifications from 'expo-notifications';

// 配置前台通知显示规则
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

const NotificationScheduler = () => {
  const startTime = new Date();
  startTime.setHours(2, 0, 0, 0); 
  const endTime = new Date();
  endTime.setHours(3, 30, 0, 0); 
  const notificationCount = 240; 
  const [notificationMessage, setNotificationMessage] = useState('暂无通知');
  const timeDifference = endTime.getTime() - startTime.getTime();
  const interval = Math.max(1, Math.round(timeDifference / notificationCount));

  useEffect(() => {
    const setupNotifications = async () => {
      // 等待权限请求完成
      const { status } = await Notifications.requestPermissionsAsync();
      if (status !== 'granted') {
        Alert.alert('权限不足', '请前往设置开启通知权限');
        return;
      }

      const currentDate = new Date();
      console.log('------ 开始调度通知 ------');
      
      for (let i = 1; i <= notificationCount; i++) {
        let triggerTime = new Date(startTime.getTime() + i * interval);
        
        // 若触发时间已过期,自动调整到次日
        if (triggerTime < currentDate) {
          triggerTime.setDate(triggerTime.getDate() + 1);
        }
        
        console.log('触发时间:', triggerTime);
        
        await Notifications.scheduleNotificationAsync({
          content: {
            title: "该检查了!",
            body: `这是第${i}条通知。`,
            data: { data: '自定义数据' },
          },
          trigger: {
            date: triggerTime, // 正确指定触发时间
          },
        });
      }
    };

    const notificationListener = Notifications.addNotificationReceivedListener(notification => {
      setNotificationMessage(notification.request.content.body);
    });

    const responseListener = Notifications.addNotificationResponseReceivedListener(response => {
      setNotificationMessage(response.notification.request.content.body);
    });

    setupNotifications();

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

  return (
    <View style={{ padding: 20, marginTop: 50 }}>
      <Text>通知已调度!</Text>
      <Text style={{ marginTop: 10 }}>最新通知: {notificationMessage}</Text>
    </View>
  );
};

export default NotificationScheduler;

额外测试建议

  • 测试时可将startTime改为当前时间后1-2分钟,快速验证推送是否生效,无需等待到凌晨。
  • 可调用Notifications.getAllScheduledNotificationsAsync()查看已调度的通知列表,确认调度是否成功。
  • 关闭APP后,需确保设备未开启省电模式或后台限制,否则可能影响通知触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 07:38:17