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

如何让Expo/React Native计时器在后台/锁屏状态下运行并发送通知?

在Expo/React Native中实现后台运行的计时器并发送通知

完全可以实现,但不能依赖前端的setTimeout/setInterval——因为当应用进入后台或锁屏时,系统会挂起JS线程,这类定时器会暂停甚至失效。推荐两种方案,根据你的需求选择:

方案1:直接使用系统定时通知(推荐,轻量且可靠)

如果你的核心需求只是「计时结束后发送通知」,不需要在后台实时更新计时状态,直接用Expo的通知API设置定时触发即可,系统会负责在指定时间触发通知,完全不受应用状态影响。

实现步骤:

  • 安装依赖:
    npx expo install expo-notifications
    
  • 请求通知权限:
    import * as Notifications from 'expo-notifications';
    
    async function requestNotificationPermissions() {
      const { status } = await Notifications.requestPermissionsAsync();
      return status === 'granted';
    }
    
  • 调度定时通知:
    // 假设需要倒计时60秒后触发通知
    async function scheduleTimerNotification(seconds) {
      const hasPermission = await requestNotificationPermissions();
      if (!hasPermission) return;
    
      await Notifications.scheduleNotificationAsync({
        content: {
          title: '计时器结束',
          body: '你的倒计时已经完成!',
          sound: true,
        },
        trigger: {
          seconds: seconds, // 延迟X秒后触发
          repeats: false,
        },
      });
    }
    

这种方案不需要后台运行JS代码,完全由系统调度,省电且稳定,是最推荐的方式。

方案2:后台持续运行计时器(适合需要实时更新状态的场景)

如果需要在后台持续运行计时器(比如实时更新剩余时间到本地存储、同步到服务器等),需要结合Expo的后台任务工具:

实现步骤:

  • 安装依赖:
    npx expo install expo-task-manager expo-background-timer expo-notifications
    
  • 注册后台任务:
    import * as TaskManager from 'expo-task-manager';
    import * as BackgroundTimer from 'expo-background-timer';
    import * as Notifications from 'expo-notifications';
    
    // 定义后台任务名称
    const TIMER_TASK = 'background-timer-task';
    
    // 注册任务
    TaskManager.defineTask(TIMER_TASK, async ({ data, error }) => {
      if (error) {
        console.error('后台任务出错:', error);
        return;
      }
    
      const { totalSeconds } = data;
      let remainingSeconds = totalSeconds;
    
      // 使用BackgroundTimer的setInterval,后台不会被挂起
      const intervalId = BackgroundTimer.setInterval(() => {
        remainingSeconds--;
        if (remainingSeconds <= 0) {
          BackgroundTimer.clearInterval(intervalId);
          // 发送通知
          Notifications.scheduleNotificationAsync({
            content: {
              title: '计时器结束',
              body: '倒计时完成!',
            },
            trigger: null, // 立即触发
          });
        }
        // 可选:更新本地存储的剩余时间
        // AsyncStorage.setItem('remainingTime', remainingSeconds.toString());
      }, 1000);
    });
    
  • 启动后台任务:
    async function startBackgroundTimer(seconds) {
      const hasPermission = await requestNotificationPermissions();
      if (!hasPermission) return;
    
      // 请求后台任务权限
      const { status } = await TaskManager.requestPermissionsAsync();
      if (status !== 'granted') {
        alert('需要开启后台任务权限才能运行');
        return;
      }
    
      // 启动任务
      await TaskManager.startTaskAsync(TIMER_TASK, {
        data: { totalSeconds: seconds },
      });
    }
    

注意事项:

  • 后台任务的运行时间会受系统限制(iOS尤其严格),长时间运行可能被系统终止;
  • 后台任务会增加电量消耗,非必要不推荐使用;
  • iOS上需要在app.json中配置后台模式:
    {
      "expo": {
        "ios": {
          "infoPlist": {
            "UIBackgroundModes": ["fetch", "remote-notification"]
          }
        }
      }
    }
    

关键提醒

  • 优先使用方案1,系统级通知更稳定且省电;
  • 无论哪种方案,都必须申请对应的权限(通知权限、后台任务权限);
  • iOS上后台任务的限制比Android更严格,测试时需要注意系统行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:35:26