How to properly request location permissions for background location updates in Flutter?

42 views Asked by At

I'm working on a Flutter app that needs to fetch location data in the background for both iOS and Android. I've updated my info.plist and AndroidManifest.xml with the necessary permissions and included the geolocator and workmanager packages. However, I'm unsure if I've set up the background fetching correctly for both platforms.

Here's how I've configured my info.plist:

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Location information is required to validate the geo coordinates while submitting random attendance</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location information is required to validate the geo coordinates while submitting attendance</string>
<key>UIBackgroundModes</key>
<array>
    <string>fetch</string>
    <string>location</string>
    <string>processing</string>
</array>

And for Android in AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

I've also included the geolocator and workmanager packages in my pubspec.yml:

geolocator: ^11.0.0
workmanager: ^0.5.2

Here's the Dart code snippet I'm working with in main.dart. I'm trying to initialize a background task to fetch location updates, but I'm unsure if I've set it up correctly. Can someone review if my task initialization and callback handling are implemented properly for Flutter?

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:smartrac_blue_dart/splashscreen/splashscreen.dart';
import 'package:workmanager/workmanager.dart';
import 'package:smartrac_blue_dart/database/bluedart_db.dart';
import 'locationService/locationService.dart';


// Workmanager task name
const fetchLocationTask = "fetchLocationTask";

void callbackDispatcher() {
  print('callbackDispatcher');
  Workmanager().executeTask((task, inputData) async {
    if (task == fetchLocationTask) {
      await LocationService().fetchAndStoreLocation(); // Call the static method for background execution
    }
    return Future.value(true);
  });
}
void main() async {
  WidgetsFlutterBinding.ensureInitialized(); // Ensure Flutter is initialized
  await Workmanager().initialize(callbackDispatcher);

  // Register a periodic task
  var uniqueID = "uniqueLocationTask"; // A more static ID is recommended
  Workmanager().registerPeriodicTask(
    uniqueID,
    fetchLocationTask,
    frequency: Duration(minutes: 2), // Adjusted to a more reasonable and platform-compliant interval
  );
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]).then((_) {
    runApp(MyApp());
  });
}


class MyApp extends StatefulWidget {
  MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // This widget is the root of your application.
  String latitude = 'Unknown';
  String longitude = 'Unknown';
  final bludartDB db_blueDart = bludartDB();
  Timer? locationTimer;

  @override
  void initState() {
    super.initState();
    // Call the web service here
    startLocationUpdates();
  }
  void startLocationUpdates() {
    print("startLocationUpdates");
    // Example of starting location updates periodically
    Timer.periodic(Duration(minutes: 5), (Timer t) async {
      await LocationService().fetchAndStoreLocation();
    });
  }
  // @override
  // void dispose() {
  //   locationTimer?.cancel(); // Cancel the timer when the widget is disposed
  //   super.dispose();
  // }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SmarTrac-BD',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SplashScreen(),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Classico'),
      ),
      body: Container(
        color: Colors.blue.shade200,
      ),
    );
  }
}
0

There are 0 answers