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

Expo Android前台位置追踪在屏幕熄灭时意外停止,轨迹记录中断

Expo Android前台位置追踪在屏幕熄灭时意外停止,轨迹记录中断

我之前做类似的Expo位置追踪功能时,也碰到过这个头疼的问题——屏幕一灭或者应用后台待久了,轨迹就断了,回来后完全不记录。结合你的代码和我踩过的坑,给你整理几个关键的修复点:

1. 先搞定电池优化这个“元凶”

Android的电池优化机制是后台任务杀手,哪怕你开了前台服务,系统还是可能在屏幕熄灭后限制你的应用。你的代码里已经有checkBatteryOptimization,但一定要在启动追踪前做检查并引导用户关闭:

  • 调用checkBatteryOptimization后,如果返回true,立刻弹提示让用户去设置里把你的应用排除在电池优化外
  • 可以用expo-intent-launcher直接跳转到电池优化设置页面,不用让用户自己找路:
    import * as IntentLauncher from 'expo-intent-launcher';
    
    // 在startTracking里添加
    const isOptimized = await checkBatteryOptimization();
    if (isOptimized) {
      showErrorToast('电池优化会影响追踪,请关闭后重试');
      await IntentLauncher.startActivityAsync(IntentLauncher.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
      return false;
    }
    
  • 另外,小米、华为、OPPO这些厂商还有自己的后台管理,一定要让用户把应用加入“后台保护”或“自启动白名单”,不然系统还是会偷偷杀进程。

2. 补全前台服务的通知渠道

Android 8.0+要求所有通知必须属于一个渠道,你的代码里定义了channelId,但没创建渠道,这会导致前台服务启动失败:

  • 在startTracking方法开头,先创建通知渠道:
    await Notifications.createChannelAsync('location-tracking', {
      name: '位置追踪通知',
      importance: Notifications.AndroidImportance.DEFAULT,
      sound: false, // 可以根据需求设置声音
      lockscreenVisibility: Notifications.AndroidNotificationVisibility.PUBLIC,
    });
    
    没有这个渠道,前台服务的通知弹不出来,系统就不会认为你的应用在前台运行,很容易被限制。

3. 完善Task Manager的任务逻辑

你的代码里没看到TaskManager.defineTask的部分,这是接收位置更新的核心!一定要正确注册任务,并且处理错误:

// 在组件外部或者useEffect里注册任务(只注册一次)
TaskManager.defineTask(LOCATION_TASK_NAME, async ({ data, error }) => {
  if (error) {
    console.error('追踪任务出错:', error);
    showErrorToast('位置追踪异常,正在尝试恢复');
    // 这里可以加个重试逻辑,但要注意避免无限循环
    return;
  }
  if (data?.locations?.length) {
    // 把拿到的位置传给你的addLocationPoint方法
    await addLocationPoint(data.locations.map(loc => ({
      latitude: loc.coords.latitude,
      longitude: loc.coords.longitude,
      accuracy: loc.coords.accuracy,
      speed: loc.coords.speed
    })));
  }
});

还要确保在启动前检查任务是否已注册:

// 在startTracking里添加
const isTaskDefined = await TaskManager.isTaskDefined(LOCATION_TASK_NAME);
if (!isTaskDefined) {
  showErrorToast('追踪任务未注册,请重启应用');
  return false;
}

4. 调整位置更新参数

你现在的timeInterval和distanceInterval都是0,这会让系统认为你需要实时更新,但系统为了省电,可能会在后台限制频率。建议设置合理的参数:

const locationConfig = {
  accuracy: Location.Accuracy.BestForNavigation,
  timeInterval: 10000, // 每10秒更新一次
  distanceInterval: 5, // 移动5米更新一次
  foregroundService: Platform.OS === 'android' ? foregroundService : undefined,
  pausesUpdatesAutomatically: false,
  activityType: ActivityType.OtherNavigation,
  mayRequireBackgroundAccess: true,
  ...(Platform.OS === 'ios' && { 
    allowsBackgroundLocationUpdates: true, 
    showsBackgroundLocationIndicator: true 
  }),
};

这样既保证了轨迹的连续性,又不会让系统觉得你的应用太耗电。

5. 增加追踪状态的持久化和恢复

当应用被意外杀死后,重启时要恢复之前的追踪状态:

  • 在startTracking成功后,把追踪状态存在AsyncStorage里:
    await AsyncStorage.setItem(StorageKeys.IS_TRACKING, 'true');
    
  • 在App启动时(比如根组件的useEffect里)检查这个状态,如果是true,自动调用startTracking恢复追踪。

按照这些步骤调整后,基本就能解决屏幕熄灭后追踪中断的问题了,我自己的项目里这么改之后,Android上的稳定性提升了很多。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.09 03:04:51