The offered code snippet is a part of a Flutter utility that makes use of the flutter_background_service
bundle to run background duties. The onStart
perform is the entry level for the background service, which is accountable for periodically amassing and updating the gadget’s location. That is working good on android, even after I shut the app. However in IOS it is working solely when app is operating or paused.
Code:
Future<void> initializeBackgroundService() async {
closing service = FlutterBackgroundService();
await service.configure(
androidConfiguration: AndroidConfiguration(
onStart: onStart,
autoStart: false,
autoStartOnBoot: false,
isForegroundMode: true,
initialNotificationTitle: "Monitoring",
initialNotificationContent: 'Refreshing',
),
iosConfiguration: IosConfiguration(
autoStart: false,
onForeground: onStart,
),
);
}
Timer? timer;
@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
print("onStart known as with $service");
strive {
DartPluginRegistrant.ensureInitialized();
String __ = "";
String model = "";
String __ = "";
String url = "";
Place? place;
if (Platform.isAndroid) {
log("gadget is android");
if (service is AndroidServiceInstance) {
log("gadget is android service occasion");
service.on('setAsForeground').pay attention((occasion) async {
//my codes
});
}
} else if (Platform.isIOS) {
service.on('setAsForeground').pay attention((occasion) async {
//my codes
});
}
if (Platform.isIOS) {
closing NotificationService notificationService = NotificationService();
await notificationService.initializePlatformNotifications();
}
service.on('stopService').pay attention((occasion) 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: "Monitoring",
content material: "Final up to date at ${DateFormat.jm().format(DateTime.now())}, ${DateFormat.yMd().format(DateTime.now())}",
);
}
} else if (Platform.isIOS) {
await NotificationService.showNotification(
id: 0,
title: "Monitoring",
physique: "Final up to date at ${DateFormat.jm().format(DateTime.now())}, ${DateFormat.yMd().format(DateTime.now())}",
knowledge: "",
);
}
timer?.cancel();
timer = Timer.periodic(const Length(seconds: 10), (timer) async {
if (Platform.isAndroid) {
log("authcode for android $authcode");
if (service is AndroidServiceInstance) {
if (await service.isForegroundService()) {
Place? place;
bool isLocationEnabled = await Geolocator.isLocationServiceEnabled();
bool isPermissionGranted = await Geolocator.checkPermission() ==
LocationPermission.whileInUse ||
await Geolocator.checkPermission() == LocationPermission.all the time;
if (isLocationEnabled && isPermissionGranted) {
place = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.bestForNavigation);
if (place.accuracy > 200) {
StreamSubscription<Place> positionStream =
Geolocator.getPositionStream(
locationSettings: AndroidSettings(
accuracy: LocationAccuracy.bestForNavigation,
distanceFilter: 0,
intervalDuration: const Length(seconds: 1),
),
).pay attention((Place worth) {
place = worth;
});
await Future.delayed(const Length(seconds: 5));
await positionStream.cancel();
}
log("authcode for android earlier than name $authcode");
log("url for android earlier than name $url");
//sending location from right here
} else {
timer.cancel();
service.stopSelf();
}
}
}
} else if (Platform.isIOS) {
Place? place;
bool isLocationEnabled = await Geolocator.isLocationServiceEnabled();
bool isPermissionGranted = await Geolocator.checkPermission() ==
LocationPermission.whileInUse ||
await Geolocator.checkPermission() == LocationPermission.all the time;
if (isLocationEnabled && isPermissionGranted) {
place = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.bestForNavigation);
if (place.accuracy > 200) {
StreamSubscription<Place> positionStream =
Geolocator.getPositionStream(
locationSettings: AppleSettings(
accuracy: LocationAccuracy.bestForNavigation,
distanceFilter: 0,
timeLimit: const Length(seconds: 1),
activityType: ActivityType.otherNavigation,
),
).pay attention((Place worth) {
place = worth;
});
await Future.delayed(const Length(seconds: 5));
await positionStream.cancel();
}
//sending location from right here
} else {
timer.cancel();
service.stopSelf();
}
}
print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}');
});
} catch (e, stack) {
print(e);
print('stack: $stack');
}
}
I configured the flutter_background_service bundle and enabled UIBackgroundModes for location updates within the Data.plist file.
<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>
And that is Appdelegate.swift
import UIKit
import Flutter
import flutter_background_service_ios
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func utility(
_ utility: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
SwiftFlutterBackgroundServicePlugin.taskIdentifier = "dev.flutter.background.refresh"
GeneratedPluginRegistrant.register(with: self)
return tremendous.utility(utility, didFinishLaunchingWithOptions: launchOptions)
}
}