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

Flutter应用Android 12后台定位失效,Android 9正常求助

Android 12下Flutter后台定位失效的解决方案

核心原因

Android 12(API 31+)对后台操作施加了更严格的限制:

  • 后台AlarmManager的触发频率被系统限制,无法像低版本那样高频执行任务
  • 后台定位需要额外的权限声明和规范的请求流程
  • 系统会限制普通后台任务的资源访问权限,Alarm触发的任务可能无法调用定位服务

具体修复步骤

1. 完善权限配置

确保AndroidManifest.xml中添加符合Android 12要求的权限:

<!-- 前台定位权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 后台定位权限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!-- Android 12+ 后台任务必需通知权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- 声明依赖GPS硬件 -->
<uses-feature android:name="android.hardware.location.gps" />

同时用permission_handler包主动请求权限,确保用户授予始终允许定位权限和通知权限:

import 'package:permission_handler/permission_handler.dart';

Future<void> requestRequiredPermissions() async {
  // 先请求前台定位权限
  var locationStatus = await Permission.locationWhenInUse.request();
  if (locationStatus.isGranted) {
    // 再请求后台定位权限
    await Permission.locationAlways.request();
  }
  // 请求通知权限(Android 12+ 后台任务必需)
  await Permission.notification.request();
}

2. 替换AndroidAlarmManager为WorkManager

Android 12限制了后台Alarm的执行,workmanager包更适配系统省电策略,是后台周期性任务的标准解决方案:

依赖配置

在pubspec.yaml中添加:

dependencies:
  workmanager: ^0.5.1

初始化与任务注册

import 'package:workmanager/workmanager.dart';

// 后台任务回调
void locationTaskDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    await liveLocation(); // 调用你的定位逻辑
    return Future.value(true);
  });
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化WorkManager
  await Workmanager().initialize(
    locationTaskDispatcher,
    isInDebugMode: false,
  );
  // 注册周期性任务(Android强制要求间隔≥15分钟)
  await Workmanager().registerPeriodicTask(
    "location-tracking",
    "track-location",
    frequency: const Duration(minutes: 15),
    initialDelay: const Duration(seconds: 5),
    constraints: Constraints(
      networkType: NetworkType.connected, // 可选:仅在联网时执行
    ),
  );
  runApp(const MyApp());
}

3. 优化定位获取逻辑

修改liveLocation函数,添加错误处理和后台适配参数:

static Future<void> liveLocation() async {
  try {
    await Firebase.initializeApp();
    final prefs = await SharedPreferences.getInstance();
    await prefs.reload();
    
    double? storedLongitude = prefs.getDouble('trackingLongitude');
    double? storedLatitude = prefs.getDouble('trackingLatitude');
    String? empname = prefs.getString('empname');

    // 配置后台可用的定位参数
    final trackingLocation = await Geolocator.getCurrentPosition(
      locationSettings: const LocationSettings(
        accuracy: LocationAccuracy.high,
        distanceFilter: 10, // 移动10米再更新,节省电量
      ),
      timeout: const Duration(seconds: 10), // 设置超时避免阻塞
    );

    // 距离计算逻辑(保留原代码)
    const R = 6371;
    final dLat = (trackingLocation.latitude - storedLatitude!) * pi / 180;
    final dLon = (trackingLocation.longitude - storedLongitude!) * pi / 180;
    final a = sin(dLat / 2) * sin(dLat / 2) +
        cos(trackingLocation.latitude * pi / 180) *
            cos(storedLatitude * pi / 180) *
            sin(dLon / 2) *
            sin(dLon / 2);
    final c = 2 * atan2(sqrt(a), sqrt(1 - a));
    final d = R * c * 1000;

    // 更新本地存储与Firebase
    await prefs.setDouble('trackingLongitude', trackingLocation.longitude);
    await prefs.setDouble('trackingLatitude', trackingLocation.latitude);
    if (empname != null) {
      await FirebaseFirestore.instance
          .collection(tasksCollectionName)
          .doc(empname)
          .collection("location")
          .doc("location")
          .set({
        'latitude': trackingLocation.latitude,
        'longitude': trackingLocation.longitude,
        'arriveTime': DateTime.now().toString().substring(11, 16),
      });
    }
  } catch (e) {
    print('定位或数据上传失败: $e');
  }
}

4. 关键注意事项

  • Android 12强制要求周期性后台任务间隔≥15分钟,设置更短间隔会被系统忽略
  • 后台定位时系统可能降低精度,若需高精度,建议前台启动定位服务后后台延续使用
  • 测试时需将应用切换到后台,等待WorkManager触发任务,调试模式下的即时执行不代表真实后台行为

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:37:49