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
相关产品推荐
相关产品推荐

