fluttergeolocationflutter-workmanagergeolocator

Can't use Geolocator inside Workmanager's task in Flutter


I am trying to use either Geolocator.getCurrentLocation or Geolocator.checkPermission() inside Workmanager's task. Both of those calls raise the same exception: MissingPluginException(No implementation found for method getCurrentPosition on channel flutter.baseflow.com/geolocator) - for getCurrentLocation.

And MissingPluginException(No implementation found for method checkPermission on channel flutter.baseflow.com/geolocator) for the checkPermission method.

Here is an example of the code

void callbackDispatcher() {
  Workmanager().executeTask((taskName, inputData) async {
    await Geolocator.checkPermission();
    await Geolocator.getCurrentPosition();
  });
}

There are few issues opened in GitHub repo of Geolocator, but there are no answers for them.

Any ideas on how I can solve this?


Solution

  • The problem is that with version 3.1.6 of the geolocator_android the default method channel implementation has been replaced by a platform specific implementation. However since the task is run in a separate isolate which executes without the Flutter engine, the platform specific implementation (in this case geolocator_android) is not registered with the platform interface (geolocator_platform_interface) resulting in the MissingPluginException.

    To use version 3.1.6 or later make sure you register the platform specific implementation when the executeTask is run.

    void callbackDispatcher() {
      Workmanager().executeTask((task, inputData) async {
       if (defaultTargetPlatform == TargetPlatform.android) {
         GeolocatorAndroid.registerWith();
       } else if (defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS) {
         GeolocatorApple.registerWith();
       } else if (defaultTargetPlatform == TargetPlatform.linux) {
         GeolocatorLinux.registerWith();
       }
    
        await Geolocator.checkPermission();
        await Geolocator.getCurrentPosition();
      });
    }
    

    Alternatively if you are running Flutter 2.11+, you can use the new DartPluginRegistrant.ensureInitialized() method to ensure all packages are registered correctly:

    void callbackDispatcher() {
      Workmanager().executeTask((task, inputData) async {
        DartPluginRegistrant.ensureInitialized();
    
        await Geolocator.checkPermission();
        await Geolocator.getCurrentPosition();
      });
    }
    

    More information can be found here and here.