I’m utilizing Flutter with flutter_background_service and geolocator to get location updates within the background.
In debug mode, background location works tremendous even when the app is minimized or the display screen is locked.
However when working in launch mode or putting in the app through TestFlight, it stops sending any background location updates.
I’ve enabled the next in Xcode
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 ultimate BackgroundServiceController _instance =
BackgroundServiceController._internal();
manufacturing facility BackgroundServiceController() => _instance;
BackgroundServiceController._internal();
ultimate FlutterBackgroundService _service = FlutterBackgroundService();
Future initializeService({
required int? disInterval,
required int? timeInterval,
}) async {
SessionController().setDistanceAndTimeInterval(
disInterval: disInterval.toString(),
timeInterval: timeInterval.toString(),
);
ultimate isRunning = await _service.isRunning();
if (isRunning) {
await Future.delayed(const Length(seconds: 1));
_service.invoke('setData');
return;
}
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'my_foreground',
'MY FOREGROUND SERVICE',
description:
'This channel is used for essential notifications.',
significance: Significance.low,
);
ultimate FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
if (Platform.isIOS || Platform.isAndroid) {
await flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(
iOS: DarwinInitializationSettings(),
android: AndroidInitializationSettings('brand'),
),
);
}
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation()
?.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 Length(milliseconds: 200));
}
await Future.delayed(const Length(seconds: 3));
_service.invoke('setData');
}
Future stopService() async {
ultimate 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();
ultimate FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
ultimate disInterval = SessionController().disInterval ?? 20;
ultimate timeInterval = SessionController().timeInterval ?? 10;
StreamSubscription? positionStream;
ultimate 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 {
ultimate 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 {
ultimate disInterval = SessionController().disInterval ?? 20;
ultimate timeInterval = SessionController().timeInterval ?? 10;
await Future.delayed(const Length(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 will not be 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 will not be 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();
ultimate homeViewModel = HomeViewModel();
attempt {
ultimate disInterval = SessionController().disInterval ?? 20;
ultimate 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 Length(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