I'm trying to build a flutter app to get the location every 2 seconds even when the app is minimised. I'm using the flutter_background_service: ^5.0.4 for the app to check location when minimised.
Using android.permission.FOREGROUND_SERVICE_LOCATION
for permission the app crashes. So, i tried with out using it but got a lot of errors.
Main code:
import 'dart:async';
import 'dart:ui';
import 'package:disable_battery_optimization/disable_battery_optimization.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:flutter_background_service_android/flutter_background_service_android.dart';
import 'package:permission_handler/permission_handler.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeService();
runApp(MyApp());
}
Future<void> initializeService() async {
final service = FlutterBackgroundService();
await service.configure(
androidConfiguration: AndroidConfiguration(
onStart: onStart,
autoStart: false,
isForegroundMode: true,
notificationChannelId: 'location_service',
initialNotificationTitle: 'Background Location Service',
initialNotificationContent: 'Fetching location...',
foregroundServiceNotificationId: 888,
),
iosConfiguration: IosConfiguration(
onForeground: onStart,
onBackground: onIosBackground,
),
);
}
@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
DartPluginRegistrant.ensureInitialized();
if (service is AndroidServiceInstance) {
service.on('foregroundService').listen((event) {
service.setAsForegroundService();
});
service.on('stopService').listen((event) {
service.stopSelf();
});
}
Timer.periodic(const Duration(seconds: 2), (timer) async {
final runCheck = FlutterBackgroundService();
if (!(await runCheck.isRunning())) timer.cancel();
if (service is AndroidServiceInstance) {
if(await service.isForegroundService()){
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.bestForNavigation,
);
print('Latitude: ${position.latitude}, Longitude: ${position.longitude}');
service.invoke(
'updateLocation',
{
'latitude': position.latitude.toString(),
'longitude': position.longitude.toString(),
},
);
}
}
});
}
@pragma('vm:entry-point')
Future<bool> onIosBackground(ServiceInstance service) async {
WidgetsFlutterBinding.ensureInitialized();
return true;
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LocationTrackerScreen(),
);
}
}
class LocationTrackerScreen extends StatefulWidget {
@override
_LocationTrackerScreenState createState() => _LocationTrackerScreenState();
}
class _LocationTrackerScreenState extends State<LocationTrackerScreen> {
String _latitude = '0.0';
String _longitude = '0.0';
@override
void initState() {
super.initState();
locationPermission();
FlutterBackgroundService().on('updateLocation').listen((event) {
setState(() {
_latitude = event?['latitude'] ?? '0.0';
_longitude = event?['longitude'] ?? '0.0';
});
});
}
Future<void> batteryOptimizationCheck()async{
DisableBatteryOptimization.showDisableBatteryOptimizationSettings();
bool? isBatteryOptimizationDisabled =
await DisableBatteryOptimization.isBatteryOptimizationDisabled;
if (isBatteryOptimizationDisabled != null) {
if(isBatteryOptimizationDisabled== true){
print("Battery optimization is ${isBatteryOptimizationDisabled ?
"Disabled" : "Enabled"}");
}
} else {
print("Could not determine battery optimization status.");
}
}
void locationPermission() async {
await batteryOptimizationCheck();
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Location services are disabled. Please enable them.')));
return;
}
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Location permissions are permanently denied.')));
return;
}
}
var accuracy = await Geolocator.getLocationAccuracy();
if (accuracy != LocationAccuracyStatus.precise) {
permission = await Geolocator.requestPermission();
accuracy = await Geolocator.getLocationAccuracy();
if (accuracy != LocationAccuracyStatus.precise) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Precise Location Permission denied, Low Accuracy')));
}
}
var alwaysPermission = await Permission.locationAlways.status;
if (!alwaysPermission.isGranted) {
var result = await Permission.locationAlways.request();
if (!result.isGranted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
'Location Always permission is required for background location tracking.')));
}
}
}
void startService() async {
final service = FlutterBackgroundService();
service.invoke('foregroundService');
var isRunning = await service.isRunning();
if (!isRunning) {
service.startService();
}
}
void stopService() async {
final service = FlutterBackgroundService();
var isRunning = await service.isRunning();
if (isRunning) {
service.invoke('stopService');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Location Tracker')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Latitude: $_latitude\nLongitude: $_longitude',
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: startService,
style: ElevatedButton.styleFrom(backgroundColor: Colors.green),
child: const Text('Start'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: stopService,
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
child: const Text('Stop'),
),
],
),
),
);
}
}
Console:
Failed to start foreground service due to SecurityException - have you fotten to request a permission? - Starting FGS with type location callerApp=ProcessRecord{4d894c2 12877:com.sfstrace.fleet/u0a238} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_LOCATION] any of the permissions allOf=false [android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_FINE_LOCATION] and the app must be in the eligible state/exemptions to access the foreground only permission
V/BackgroundService(12877): Starting flutter engine for background service
W/BackgroundService(12877): Failed to start foreground service due to SecurityException - have you fotten to request a permission? - Starting FGS with type location callerApp=ProcessRecord{4d894c2 12877:com.sfstrace.fleet/u0a238} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_LOCATION] any of the permissions allOf=false [android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_FINE_LOCATION] and the app must be in the eligible state/exemptions to access the foreground only permission
D/FlutterArchivePlugin(12877): onAttachedToEngine - IN
D/FlutterArchivePlugin(12877): doOnAttachedToEngine - IN
D/FlutterArchivePlugin(12877): doOnAttachedToEngine - OUT
D/FlutterArchivePlugin(12877): onAttachedToEngine - OUT
V/BackgroundService(12877): Service already running, using existing service
D/FlutterGeolocator(12877): Geolocator foreground service connected
D/FlutterGeolocator(12877): Initializing Geolocator services
D/FlutterGeolocator(12877): Flutter engine connected. Connected engine count 2
I/flutter (12877): `flutter_background_service_android` threw an error: Exception: This class should only be used in the main isolate (UI App). The app may not function as expected until you remove this plugin from pubspec.yaml
D/EGL_emulation(12877): app_time_stats: avg=1585.87ms min=9.88ms max=4736.17ms count=3
E/flutter (12877): [ERROR:flutter/runtime/dart_vm_initializer(41)] Unhandled Exception: MissingPluginException(No implementation found for method isServiceRunning on channel id.flutter/background_service/android/method)
E/flutter (12877): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332:7)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877): #1 FlutterBackgroundServiceAndroid.isServiceRunning (package:flutter_background_service_android/flutter_background_service_android.dart:127:18)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877): #2 onStart.<anonymous closure> (package:demo_speedo/main.dart:52:11)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877):
E/flutter (12877): [ERROR:flutter/runtime/dart_vm_initializer(41)] Unhandled Exception: MissingPluginException(No implementation found for method isServiceRunning on channel id.flutter/background_service/android/method)
E/flutter (12877): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332:7)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877): #1 FlutterBackgroundServiceAndroid.isServiceRunning (package:flutter_background_service_android/flutter_background_service_android.dart:127:18)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877): #2 onStart.<anonymous closure> (package:demo_speedo/main.dart:52:11)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877):
E/flutter (12877): [ERROR:flutter/runtime/dart_vm_initializer(41)] Unhandled Exception: MissingPluginException(No implementation found for method isServiceRunning on channel id.flutter/background_service/android/method)
E/flutter (12877): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332:7)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877): #1 FlutterBackgroundServiceAndroid.isServiceRunning (package:flutter_background_service_android/flutter_background_service_android.dart:127:18)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877): #2 onStart.<anonymous closure> (package:demo_speedo/main.dart:52:11)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877):
E/flutter (12877): [ERROR:flutter/runtime/dart_vm_initializer(41)] Unhandled Exception: MissingPluginException(No implementation found for method isServiceRunning on channel id.flutter/background_service/android/method)
E/flutter (12877): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332:7)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877): #1 FlutterBackgroundServiceAndroid.isServiceRunning (package:flutter_background_service_android/flutter_background_service_android.dart:127:18)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877): #2 onStart.<anonymous closure> (package:demo_speedo/main.dart:52:11)
E/flutter (12877): <asynchronous suspension>
E/flutter (12877):
Manifest:
<manifest xmlns:android=";>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_FOREGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
<application
android:label="SFS Fleet Tracker"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
android:value="2"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<service
android:name="id.flutter.flutter_background_service.BackgroundService"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="location" />
</application>
<!-- Required to query activities that can process text, see:
and
.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
I'm a beginner trying to solve this issue.