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

Flutter iOS应用关闭后后台定位更新失效问题求助

Flutter iOS后台定位失效问题

我开发的Flutter应用使用flutter_background_service包实现后台定位任务,onStart函数作为后台服务入口,负责定期采集并更新设备位置。该功能在Android端表现正常,即使关闭应用也能持续运行,但在iOS端仅能在应用处于运行或暂停状态时生效。

我已完成以下配置和代码编写:

已完成的配置

Info.plist配置

<key>BGTaskSchedulerPermittedIdentifiers</key>
    <array>
        <string>dev.flutter.background.refresh</string>
        <string>myBackgroundTask</string>
    </array>
<key>UIBackgroundModes</key>
    <array>
        <string>location</string>
        <string>fetch</string>
        <string>remote-notification</string>
    </array>

AppDelegate.swift配置

import UIKit
import Flutter
import flutter_background_service_ios

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        SwiftFlutterBackgroundServicePlugin.taskIdentifier = "dev.flutter.background.refresh"
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

核心代码实现

后台服务初始化函数

Future<void> initializeBackgroundService() async {
  final service = FlutterBackgroundService();

  await service.configure(
    androidConfiguration: AndroidConfiguration(
      onStart: onStart,
      autoStart: false,
      autoStartOnBoot: false,
      isForegroundMode: true,
      initialNotificationTitle: "Tracking",
      initialNotificationContent: 'Refreshing',
    ),
    iosConfiguration: IosConfiguration(
      autoStart: false,
      onForeground: onStart,
    ),
  );
}

后台服务入口函数onStart

Timer? timer;

@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  print("onStart called with $service");
  try {
    DartPluginRegistrant.ensureInitialized();
    String __ = "";
    String version = "";
    String __ = "";
    String url = "";
    Position? position;

    if (Platform.isAndroid) {
      log("device is android");
      if (service is AndroidServiceInstance) {
        log("device is android service instance");
        service.on('setAsForeground').listen((event) async {
          //自定义业务代码
        });
      }
    } else if (Platform.isIOS) {
      service.on('setAsForeground').listen((event) async {
        //自定义业务代码
      });
    }

    if (Platform.isIOS) {
      final NotificationService notificationService = NotificationService();
      await notificationService.initializePlatformNotifications();
    }

    service.on('stopService').listen((event) async {
      timer?.cancel();
      await service.stopSelf();
      log("Service stopped");
    });

    if (Platform.isAndroid) {
      log("first notification android");
      if (service is AndroidServiceInstance && await service.isForegroundService()) {
        service.setForegroundNotificationInfo(
          title: "Tracking",
          content: "Last updated at ${DateFormat.jm().format(DateTime.now())}, ${DateFormat.yMd().format(DateTime.now())}",
        );
      }
    } else if (Platform.isIOS) {
      await NotificationService.showNotification(
        id: 0,
        title: "Tracking",
        body: "Last updated at ${DateFormat.jm().format(DateTime.now())}, ${DateFormat.yMd().format(DateTime.now())}",
        data: "",
      );
    }

    timer?.cancel();
    timer = Timer.periodic(const Duration(seconds: 10), (timer) async {
      if (Platform.isAndroid) {
        log("authcode for android $authcode");
        if (service is AndroidServiceInstance) {
          if (await service.isForegroundService()) {
            Position? position;
            bool isLocationEnabled = await Geolocator.isLocationServiceEnabled();
            bool isPermissionGranted = await Geolocator.checkPermission() ==
                LocationPermission.whileInUse ||
                await Geolocator.checkPermission() == LocationPermission.always;
            if (isLocationEnabled && isPermissionGranted) {
              position = await Geolocator.getCurrentPosition(
                  desiredAccuracy: LocationAccuracy.bestForNavigation);
              if (position.accuracy > 200) {
                StreamSubscription<Position> positionStream =
                Geolocator.getPositionStream(
                  locationSettings: AndroidSettings(
                    accuracy: LocationAccuracy.bestForNavigation,
                    distanceFilter: 0,
                    intervalDuration: const Duration(seconds: 1),
                  ),
                ).listen((Position value) {
                  position = value;
                });
                await Future.delayed(const Duration(seconds: 5));
                await positionStream.cancel();
              }
              log("authcode for android before call $authcode");
              log("url for android before call $url");
              //发送位置的业务逻辑
            } else {
              timer.cancel();
              service.stopSelf();
            }
          }
        }
      } else if (Platform.isIOS) {
        Position? position;
        bool isLocationEnabled = await Geolocator.isLocationServiceEnabled();
        bool isPermissionGranted = await Geolocator.checkPermission() ==
            LocationPermission.whileInUse ||
            await Geolocator.checkPermission() == LocationPermission.always;
        if (isLocationEnabled && isPermissionGranted) {
          position = await Geolocator.getCurrentPosition(
              desiredAccuracy: LocationAccuracy.bestForNavigation);
          if (position.accuracy > 200) {
            StreamSubscription<Position> positionStream =
            Geolocator.getPositionStream(
              locationSettings: AppleSettings(
                accuracy: LocationAccuracy.bestForNavigation,
                distanceFilter: 0,
                timeLimit: const Duration(seconds: 1),
                activityType: ActivityType.otherNavigation,
              ),
            ).listen((Position value) {
              position = value;
            });
            await Future.delayed(const Duration(seconds: 5));
            await positionStream.cancel();
          }
         //发送位置的业务逻辑
        
        } else {
          timer.cancel();
          service.stopSelf();
        }
      }
      print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}');
    });
  } catch (e, stack) {
    print(e);
    print('stack: $stack');
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:04:58