functionfluttermethodslocationworkmanagers

Flutter: Trying to access location data in background using location and workManager plugin


Issue in brief: trying to access location data of the user in background using location and workManager plugin. Currently with the code mentioned below i am able to access the location information if the application is open, Since callbackDispatcher is a top level function i am not able to call the location plugin. location plugin works when a call is done inside of the class. I am trying a way to access _getlocation() from callbackDispatcher, I am getting PlatformException(NO_ACTIVITY).

Things I have tried: found few other guys facing similar issue here, here and here Tired all these steps and no luck.

import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:workmanager/workmanager.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

Location location = new Location();

void callbackDispatcher() {
  Workmanager.executeTask((task, inputData) {
    if (task == "simplePeriodicTask") {
      print("task working");
      _getLocation();
    }
    return Future.value(true);
  });
}

LocationData _location;
String _error;
double lat;
double long;
_getLocation() async {
  _error = null;

  try {
    var _locationResult = await location.getLocation();

    _location = _locationResult;
    lat = _location.latitude;
    long = _location.longitude;
  } on PlatformException catch (err) {
    _error = err.code;
  }

  if (_error == null) {
    // _check();
    print(lat);
  } else {
    //dialog
    print(_error);
  }
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    Workmanager.initialize(
        callbackDispatcher, // The top level function, aka callbackDispatcher
        isInDebugMode:
            true // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
        );
    _checkPermissions();
  }

  // Permission for location
  PermissionStatus _permissionGranted;
  // final Location location = new Location();

  _checkPermissions() async {
    PermissionStatus permissionGrantedResult = await location.hasPermission();
    setState(() {
      _permissionGranted = permissionGrantedResult;
    });
    if (_permissionGranted == PermissionStatus.DENIED) {
      _requestPermission();
    } else if (_permissionGranted == PermissionStatus.GRANTED) {
      _checkService();
    }
  }

  _requestPermission() async {
    if (_permissionGranted != PermissionStatus.GRANTED) {
      PermissionStatus permissionRequestedResult =
          await location.requestPermission();
      setState(() {
        _permissionGranted = permissionRequestedResult;
      });
      if (permissionRequestedResult != PermissionStatus.GRANTED) {
        return;
      } else if (permissionRequestedResult == PermissionStatus.GRANTED) {
        _checkService();
      }
    }
  }
  //Permission ends

//services enabled function
  bool _serviceEnabled;
  _checkService() async {
    bool serviceEnabledResult = await location.serviceEnabled();
    setState(() {
      _serviceEnabled = serviceEnabledResult;
    });
    if (_serviceEnabled == false) {
      _requestService();
    } else {
      // _getLocation();
    }
  }

  _requestService() async {
    if (_serviceEnabled == null || !_serviceEnabled) {
      bool serviceRequestedResult = await location.requestService();
      setState(() {
        _serviceEnabled = serviceRequestedResult;
      });
      if (!serviceRequestedResult) {
        return;
      } else {
        // _getLocation();
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dart'),
      ),
      body: Column(children: <Widget>[
        RaisedButton(
            child: Text('get Location'),
            onPressed: () {
              Workmanager.registerPeriodicTask(
                "2",
                "simplePeriodicTask",
                // When no frequency is provided the default 15 minutes is set.
                // Minimum frequency is 15 min. Android will automatically change your frequency to 15 min if you have configured a lower frequency.
              );
              print('task registered');
              _getLocation();
            }),
        RaisedButton(
          onPressed: () async {
            await Workmanager.cancelAll();
            print('task Destroyd');
          },
          child: Text("cancel"),
        ),
      ]),
    );
  }
}

Trying to access _getlocation() from callbackDispatcher(); Any help on this is greatly appreciated.


Solution

  • I was facing same issue recently. location package not work with WorkManager plugin, I dont know the reason but here is my solution;

      /// This Function calls only from WorkManager 
      /// Used GeoLocator instead of Location package due to PlatformException(NO_ACTIVITY) error throwing
    
              Future<String> getPlaceMarkLocationWhileAppOff() async {
                Geolocator geoLocator = Geolocator()..forceAndroidLocationManager = true;
                var _position = await geoLocator.getCurrentPosition(
                    // desiredAccuracy: LocationAccuracy.high,
                    );
                var value = await geoLocator.placemarkFromCoordinates(_position.latitude, _position.longitude);
                return _placeMark = "${value.first.subLocality}\n${value.first.subAdministrativeArea}";
              }
    

    Used Geolocator package when app offline and used Location package when app online..

    I hope it will help..