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

如何在Expo Android应用中实现可更新的已用时间计时器通知

Expo Android通知实时更新计时器流逝时间方案

要实现Expo应用在Android通知中实时显示计时器流逝时间,核心是利用前台服务(保持后台运行)结合通知更新API,以下是具体实现步骤:

一、安装依赖

需要三个核心库:

npx expo install expo-notifications expo-task-manager expo-foreground-service

二、配置权限与项目设置

在app.json中添加Android权限和通知配置:

{
  "expo": {
    "android": {
      "permissions": ["POST_NOTIFICATIONS", "WAKE_LOCK"],
      "useNextNotificationsApi": true
    }
  }
}

三、代码实现

1. 核心逻辑封装

import { useState, useEffect } from 'react';
import { Button, View } from 'react-native';
import * as Notifications from 'expo-notifications';
import * as ForegroundService from 'expo-foreground-service';

export default function TimerScreen() {
  const [elapsedTime, setElapsedTime] = useState(0);
  const [timerInterval, setTimerInterval] = useState(null);

  // 请求通知权限 + 初始化通知通道
  useEffect(() => {
    async function setupNotifications() {
      const { status } = await Notifications.requestPermissionsAsync();
      if (status !== 'granted') {
        alert('需开启通知权限才能显示计时器通知');
        return;
      }
      // 为Android 8.0+创建通知通道
      await Notifications.setNotificationChannelAsync('timer-channel', {
        name: '计时器通知',
        importance: Notifications.AndroidImportance.DEFAULT,
        sound: null, // 避免更新通知时重复响铃
      });
    }
    setupNotifications();

    // 组件卸载时清理计时器与通知
    return () => {
      if (timerInterval) clearInterval(timerInterval);
      ForegroundService.stopAsync();
    };
  }, []);

  // 启动计时器与前台服务
  const startTimer = async () => {
    // 启动前台服务(确保后台持续运行)
    await ForegroundService.startAsync('timer-service', {
      title: '计时器运行中',
      body: '已流逝时间: 0分0秒',
      icon: require('./assets/timer-icon.png'), // 替换为你的通知图标路径
      channelId: 'timer-channel',
    });

    // 每秒更新时间与通知
    const interval = setInterval(() => {
      setElapsedTime(prevTime => {
        const newTime = prevTime + 1;
        const minutes = Math.floor(newTime / 60);
        const seconds = newTime % 60;
        // 更新前台服务的通知内容
        ForegroundService.updateNotificationAsync('timer-service', {
          title: '计时器运行中',
          body: `已流逝时间: ${minutes}分${seconds}秒`,
        });
        return newTime;
      });
    }, 1000);
    setTimerInterval(interval);
  };

  // 停止计时器与前台服务
  const stopTimer = async () => {
    if (timerInterval) clearInterval(timerInterval);
    setTimerInterval(null);
    setElapsedTime(0);
    await ForegroundService.stopAsync();
  };

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', gap: 20 }}>
      <Button title="启动计时器" onPress={startTimer} />
      <Button title="停止计时器" onPress={stopTimer} />
    </View>
  );
}

2. 关键细节说明

  • 前台服务:Android系统对后台进程限制严格,前台服务会将应用标记为"正在活跃",避免被系统回收,同时强制显示通知(这也是我们用来展示计时器的载体)。
  • 通知更新:通过ForegroundService.updateNotificationAsync复用同一个通知ID,实现内容实时覆盖更新,无需重复创建新通知。
  • 权限处理:必须请求POST_NOTIFICATIONS权限(Android 12+强制要求),否则无法显示通知。

四、注意事项

  • 通知图标需符合Android规范:建议使用24x24dp的透明图标,放在android/app/src/main/res/drawable/目录下,或通过Expo Asset加载。
  • Doze模式优化:若需在Doze模式下保持高精度计时,可额外申请REQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限,但需向用户说明用途。
  • 测试场景:务必测试APP在后台、锁屏状态下的通知更新效果,确保计时器正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:00:34