iOS background location works in Debug however not in Launch (Flutter)

0
1
iOS background location works in Debug however not in Launch (Flutter)


I’m utilizing Flutter with flutter_background_service and geolocator to get location updates within the background.

In debug mode, background location works high-quality even when the app is minimized or the display is locked.

However when working in launch mode or putting in the app by way of TestFlight, it stops sending any background location updates.

I’ve enabled the next in Xcode

Background Modes

data.plist

UIBackgroundModes

    fetch
    location
    remote-notification
    processing


NSLocationAlwaysAndWhenInUseUsageDescription
Your location is required even when the app is within the background to trace journeys.

NSLocationAlwaysUsageDescription
Your location is required even when the app is within the background to trace journeys.

NSLocationTemporaryUsageDescriptionDictionary

    LocationTracking
    This app wants exact location for varsity bus monitoring and security monitoring functions.


NSLocationWhenInUseUsageDescription
Your location is required to trace journeys whereas the app is open.

BGTaskSchedulerPermittedIdentifiers

    dev.flutter.background.refresh

BackgorundService

class BackgroundServiceController extends ChangeNotifier {
  static last BackgroundServiceController _instance =
      BackgroundServiceController._internal();
  manufacturing unit BackgroundServiceController() => _instance;
  BackgroundServiceController._internal();
  last FlutterBackgroundService _service = FlutterBackgroundService();

  Future initializeService({
    required int? disInterval,
    required int? timeInterval,
  }) async {
    SessionController().setDistanceAndTimeInterval(
      disInterval: disInterval.toString(),
      timeInterval: timeInterval.toString(),
    );

    last isRunning = await _service.isRunning();
    if (isRunning) {
      await Future.delayed(const Period(seconds: 1));
      _service.invoke('setData');
      return;
    }

    const AndroidNotificationChannel channel = AndroidNotificationChannel(
      'my_foreground', 
      'MY FOREGROUND SERVICE', 
      description:
          'This channel is used for necessary notifications.', 
      significance: Significance.low, 
    );

    last FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
        FlutterLocalNotificationsPlugin();

    if (Platform.isIOS || Platform.isAndroid) {
      await flutterLocalNotificationsPlugin.initialize(
        const InitializationSettings(
          iOS: DarwinInitializationSettings(),
          android: AndroidInitializationSettings('emblem'),
        ),
      );
    }
    await flutterLocalNotificationsPlugin
        .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin
        >()
        ?.createNotificationChannel(channel);
    await _service.configure(
      androidConfiguration: AndroidConfiguration(
        onStart: onStart,
        autoStart: true,
        isForegroundMode: true,
        autoStartOnBoot: true,
        notificationChannelId: 'my_foreground',
        initialNotificationTitle: 'Location Service',
        initialNotificationContent: 'Initializing...',
        foregroundServiceNotificationId: 888,

        foregroundServiceTypes: [AndroidForegroundType.location],
      ),
      iosConfiguration: IosConfiguration(
        autoStart: true,
        onForeground: onStart,
        onBackground: onIosBackground,
      ),
    );

    attempt {
      await _service.startService();
    } catch (e) {

    }
    whereas (!(await _service.isRunning())) {
      await Future.delayed(const Period(milliseconds: 200));
    }
    await Future.delayed(const Period(seconds: 3));
    _service.invoke('setData');
  }

  Future stopService() async {
    last isRunning = await _service.isRunning();
    if (isRunning) {
      _service.invoke("stopService");
    } else {
    }
  }

  Future isServiceRunning() async {
    return await _service.isRunning();
  }
}

@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  // DartPluginRegistrant.ensureInitialized();

  WidgetsFlutterBinding.ensureInitialized();
  await AppConstants.init();
  await SessionController().init();
  last FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();
  last disInterval = SessionController().disInterval ?? 20;
  last timeInterval = SessionController().timeInterval ?? 10;
  StreamSubscription? positionStream;
  last homeViewModel = HomeViewModel();

  void startLocationTracking() async {
    if (positionStream != null) {
      return;
    }

    DateTime? lastSentTime;
    positionStream =
        Geolocator.getPositionStream(
          locationSettings: const LocationSettings(
            distanceFilter: 0,
            accuracy: LocationAccuracy.bestForNavigation,
          ),
        ).pay attention((place) async {
          last now = DateTime.now();

          if (lastSentTime == null ||
              now.distinction(lastSentTime!).inSeconds >= (timeInterval)) {
            lastSentTime = now;

            attempt {
              await homeViewModel.pushLiveLocation(place: place);
            } catch (e) {
            }
          } else {
          }
        });
  }

  service.on('stopService').pay attention((occasion) async {
    await positionStream?.cancel();
    positionStream = null;
    await service.stopSelf();
  });

  service.on('setData').pay attention((knowledge) async {
    last disInterval = SessionController().disInterval ?? 20;
    last timeInterval = SessionController().timeInterval ?? 10;

    await Future.delayed(const Period(seconds: 5));
    startLocationTracking();
  });

  if (service is AndroidServiceInstance &&
      await service.isForegroundService()) {
    flutterLocalNotificationsPlugin.present(
      888,

      'Monitoring location in background',
      'Background location is on to maintain the app up-tp-date along with your location. That is required for foremost options to work correctly when the app just isn't working.',
      const NotificationDetails(
        android: AndroidNotificationDetails(
          'my_foreground',
          'MY FOREGROUND SERVICE',
          icon: 'ic_stat_notification', 
          ongoing: true,
          styleInformation: BigTextStyleInformation(
            'Background location is on to maintain the app up-to-date along with your location. '
            'That is required for foremost options to work correctly when the app just isn't working.',
            contentTitle: 'Monitoring location in background',
            htmlFormatContent: true,
          ),
        ),
      ),
    );

    // service.setForegroundNotificationInfo(
    //   title: "Location Monitoring",
    //   content material: "Monitoring your location in background",
    // );
  }
}

@pragma('vm:entry-point')
Future onIosBackground(ServiceInstance service) async {
  // DartPluginRegistrant.ensureInitialized();
  WidgetsFlutterBinding.ensureInitialized();
  await AppConstants.init();
  await SessionController().init();
  last homeViewModel = HomeViewModel();
  attempt {
    last disInterval = SessionController().disInterval ?? 20;

    last sub =
        Geolocator.getPositionStream(
          locationSettings: const LocationSettings(
            distanceFilter: 0,

            accuracy: LocationAccuracy.bestForNavigation,
          ),
        ).pay attention((place) async {
          attempt {
            await homeViewModel.pushLiveLocation(place: place);
          } catch (e) {
          }
        });

    await Future.delayed(const Period(seconds: 30));
    await sub.cancel();
  } catch (e) {
  }

  return true;
}

I additionally checked that the app has At all times Permit location permission in iOS Settings

LEAVE A REPLY

Please enter your comment!
Please enter your name here