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

如何在Expo应用关闭超过4小时后定时推送特定时间的通知

如何在Expo应用关闭超过4小时后定时推送特定时间的通知

看起来你已经搞定了基础的定时通知,现在就差加个“应用后台/关闭超4小时”的条件对吧?我来给你拆解下具体怎么实现,核心思路就是记录应用最后活跃的时间,然后在要触发通知的时候检查这个时间差是否符合要求。

1. 安装必要依赖

你需要用到持久化存储工具来保存活跃时间,还有后台任务管理器来实现带条件的定时触发。先执行安装命令:

npx expo install @react-native-async-storage/async-storage expo-task-manager

2. 记录应用最后活跃时间

我们要监听应用状态变化,当应用从前台切到后台/关闭时,把当前时间存到本地存储里;同时应用启动回到前台时,也更新一下活跃时间,确保记录的是最新的交互时间。

在你的根组件里添加以下代码:

import AsyncStorage from '@react-native-async-storage/async-storage';
import { AppState } from 'react-native';
import * as TaskManager from 'expo-task-manager';

// 监听应用状态
const [appState, setAppState] = useState(AppState.currentState);

// 保存最后活跃时间到本地
const saveLastActiveTime = async () => {
  try {
    await AsyncStorage.setItem('lastActiveTime', Date.now().toString());
  } catch (e) {
    console.error('保存活跃时间失败:', e);
  }
};

useEffect(() => {
  const subscription = AppState.addEventListener('change', nextAppState => {
    // 当应用从活跃状态切换到后台/非活跃时,记录时间
    if (appState === 'active' && nextAppState.match(/inactive|background/)) {
      saveLastActiveTime();
    }
    setAppState(nextAppState);
  });

  // 组件卸载时移除监听
  return () => subscription.remove();
}, [appState]);

// 应用启动时,先更新一次活跃时间
useEffect(() => {
  saveLastActiveTime();
}, []);

3. 创建后台任务检查条件并发送通知

直接用Expo的定时通知没法加条件判断,所以我们需要创建一个后台任务,让它在每天指定时间(比如8点)触发,然后在任务里检查活跃时间差,符合条件再发送通知。

添加后台任务的定义:

// 定义唯一的后台任务名称
const DAILY_REMINDER_TASK = 'dailyReminderTask';

// 注册后台任务
TaskManager.defineTask(DAILY_REMINDER_TASK, async () => {
  try {
    // 读取本地存储的最后活跃时间
    const lastActiveTimeStr = await AsyncStorage.getItem('lastActiveTime');
    if (!lastActiveTimeStr) return;

    const lastActiveTime = parseInt(lastActiveTimeStr, 10);
    const currentTime = Date.now();
    // 计算时间差(小时)
    const hoursDiff = (currentTime - lastActiveTime) / (1000 * 60 * 60);

    // 满足超过4小时的条件,发送通知
    if (hoursDiff > 4) {
      await Notifications.scheduleNotificationAsync({
        content: {
          title: '你的专属提醒',
          body: '已经4小时没打开应用啦,快回来看看~',
          // 可自定义更多通知内容
        },
        trigger: null, // 立即发送
      });
    }
  } catch (e) {
    console.error('后台任务执行出错:', e);
  }
});

4. 调度后台任务到指定时间

最后在应用启动时,请求必要权限并把后台任务调度到每天8点执行:

useEffect(() => {
  const setupTask = async () => {
    // 请求通知权限
    const { status } = await Notifications.getPermissionsAsync();
    if (status !== 'granted') {
      await Notifications.requestPermissionsAsync();
    }

    // 检查任务是否已注册,避免重复调度
    const isRegistered = await TaskManager.isTaskRegisteredAsync(DAILY_REMINDER_TASK);
    if (!isRegistered) {
      // 调度任务每天8点触发
      await Notifications.scheduleNotificationAsync({
        content: {
          // 这里的内容不会显示,仅作为后台任务的触发载体
          title: '后台任务触发器',
          body: '请勿删除此通知配置',
        },
        trigger: {
          hour: 8,
          minute: 0,
          repeats: true, // 每天重复
        },
        task: DAILY_REMINDER_TASK, // 指定触发的后台任务
      });
    }
  };

  setupTask();
}, []);

一些注意点

  • iOS后台限制:iOS对后台任务管控较严,长时间关闭应用后,定时任务可能被系统暂停,但日常使用场景下基本能正常触发。
  • 测试方法:开发时可以用TaskManager.executeTaskAsync(DAILY_REMINDER_TASK)手动触发任务,验证逻辑是否正确。
  • 权限问题:一定要确保用户授予了通知权限,否则后台任务和通知都无法正常工作。

把这些代码整合到你的根组件里,替换原来的定时通知逻辑,就能实现你想要的功能啦!

备注:内容来源于stack exchange,提问作者Takodana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 08:59:31