question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

MissingPluginException when using in isolate with Android Alarm Service

See original GitHub issue

Describe the bug I’m trying to get device location in a callback of android_alarm_service. So I create a new alarm:

AndroidAlarmManager.periodic(
              Duration(minutes: 1),
              1,
              updateDeviceLocation,
              wakeup: true,
            );

Then updateDeviceLocation is called in a separate isolate in this case. Here is the function:

static void updateDeviceLocation() {
    print("Starting device location update...");
    SharedPreferences.getInstance().then((prefs){
      print("... loading settings");
      String url = prefs.getString('app-webhook-url');
      if (url != null && url.isNotEmpty) {
        print("... done. Getting device location...");
        try {
          var location = new Location();
          location.getLocation().then((currentLocation){
            print("... done. Sending data home...");
            Map<String, String> headers = {};
            headers["Content-Type"] = "application/json";
            var data = {
              "type": "update_location",
              "data": {
                "gps": [currentLocation.latitude, currentLocation.longitude],
                "gps_accuracy": currentLocation.accuracy,
                "battery": 45
              }
            };
            http.post(
                url,
                headers: headers,
                body: json.encode(data)
            );
          });
        } on PlatformException catch (e) {
          if (e.code == 'PERMISSION_DENIED') {
            print("... no location permission. Aborting");
          }
        }
      } else {
        print("... no webhook. Aborting");
      }
    });
  }

If I call updateDeviceLocation directly in main isolate all works fine. But when updateDeviceLocation called by Alarm Manager in a separate isolate I’m getting:

Unhandled Exception: MissingPluginException(No implementation found for method getLocation on channel lyokone/location)

I tried flutter clean, restarting and rebuilding everything, but no luck.

Expected behavior I hope this plugin can work fine in a separate isolate.

Tested on:

  • Android 9, API Level 28, real device

Additional logs

I/flutter (14499): Starting device location update...
I/flutter (14499): ... loading settings
I/flutter (14499): ... checking settings
I/flutter (14499): ... done. Getting device location...
E/flutter (14499): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: MissingPluginException(No implementation found for method getLocation on channel lyokone/location)
E/flutter (14499): #0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:314:7)
E/flutter (14499): <asynchronous suspension>
E/flutter (14499): #1      Location.getLocation (package:location/location.dart:61:8)
E/flutter (14499): #2      PremiumFeaturesManager.updateDeviceLocation.<anonymous closure> (package:hass_client/premium_features_manager.class.dart:22:20)
E/flutter (14499): #3      _rootRunUnary (dart:async/zone.dart:1132:38)
E/flutter (14499): #4      _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter (14499): #5      _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
E/flutter (14499): #6      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
E/flutter (14499): #7      Future._propagateToListeners (dart:async/future_impl.dart:668:32)
E/flutter (14499): #8      Future._complete (dart:async/future_impl.dart:473:7)
E/flutter (14499): #9      _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
E/flutter (14499): #10     _AsyncAwaitCompleter.complete.<anonymous closure> (dart:async-patch/async_patch.dart:33:20)
E/flutter (14499): #11     _rootRun (dart:async/zone.dart:1120:38)
E/flutter (14499): #12     _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (14499): #13     _CustomZone.runGuarded (dart:async/zone.dart:923:7)
E/flutter (14499): #14     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963:23)
E/flutter (14499): #15     _rootRun (dart:async/zone.dart:1124:13)
E/flutter (14499): #16     _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (14499): #17     _CustomZone.runGuarded (dart:async/zone.dart:923:7)
E/flutter (14499): #18     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963:23)
E/flutter (14499): #19     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (14499): #20     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:5
  • Comments:32 (6 by maintainers)

github_iconTop GitHub Comments

4reactions
Lyokonecommented, Feb 4, 2020

Hey ! Sorry for the huge delay in response, I was mostly away from my computer this last months. I’ll look into that as soon as possible !

2reactions
jafar96commented, Jun 2, 2020

Hey guys. I finally fixed this problem. I used background_fetch package into android_alarm_manager and worked for me. you can do following steps :

Note : since I need to get Location every 1 minute and minimum period of background_fetch is 15 minutes , I do this. in other words I start and stop background_fetch every 1 minute by android_alarm_manager.

in main.dart :

main.dart

void getLocation() async{
  Location location = Location();
  LocationData locationData = await location.getLocation();
  print(locationData.latitude);
  // do something else
}

void myAlarmManager()async {
        BackgroundFetch.scheduleTask(TaskConfig(
          taskId: 'getLocation',
          delay: 1000,
          enableHeadless: true,
          stopOnTerminate: false,
          forceAlarmManager: true,
          startOnBoot: true,
        ));
}

void backgroundFetchHeadlessTask(String taskId) async {
  print("[BackgroundFetch] Headless event received: $taskId");
  getLocation();
  BackgroundFetch.finish(taskId);
  BackgroundFetch.stop();
}

void main() async{
  final backgroundLocationID = 0;
  WidgetsFlutterBinding.ensureInitialized();
  await AndroidAlarmManager.initialize();
  runApp(InspectorApp());
  BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
  await AndroidAlarmManager.periodic(
    const Duration(minutes: 1),
    backgroundLocationID,
    myAlarmManager,
    rescheduleOnReboot: true,
  );
}

.......
class MyAppState extends State<MyApp>{
 
 ......
  @override
  void initState() {
    initPlatformState();
    super.initState();
  }
  

  void initPlatformState() async {
    // Configure BackgroundFetch.
    BackgroundFetch.configure(BackgroundFetchConfig(
      minimumFetchInterval: 15,
      forceAlarmManager: false,
      stopOnTerminate: false,
      startOnBoot: true,
      enableHeadless: true,
      requiresBatteryNotLow: false,
      requiresCharging: false,
      requiresStorageNotLow: false,
      requiresDeviceIdle: false,
      requiredNetworkType: NetworkType.ANY,
    ), _onBackgroundFetch).then((int status) {
      print('[BackgroundFetch] configure success: $status');
    }).catchError((e) {
      print('[BackgroundFetch] configure ERROR: $e');
    });
    if (!mounted) return;
  }

  void _onBackgroundFetch(String taskId) async {
    print("[BackgroundFetch] Event received: $taskId");
    getLocation();
    BackgroundFetch.finish(taskId);
    BackgroundFetch.stop();
  }

}

create a new class and named it MyApplication.java.

MyApplication.java

package yourPackageName;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin;
import io.flutter.plugins.androidalarmmanager.AlarmService;
import io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin;
import com.lyokone.location.LocationPlugin;
import com.transistorsoft.flutter.backgroundfetch.BackgroundFetchPlugin;

public class MyApplication extends FlutterApplication implements PluginRegistrantCallback {
    @Override
    public void onCreate() {
        super.onCreate();
        AlarmService.setPluginRegistrant(this);
    }

    @Override
    public void registerWith(PluginRegistry registry) {
        AndroidAlarmManagerPlugin.registerWith(registry.registrarFor("io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin"));
        SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));
        LocationPlugin.registerWith(registry.registrarFor("com.lyokone.location.LocationPlugin"));
        BackgroundFetchPlugin.registerWith(registry.registrarFor("com.transistorsoft.flutter.backgroundfetch.BackgroundFetchPlugin"));
    }
}

and set name attribute in application tag to “.MyApplication”

I hope to work for you

Read more comments on GitHub >

github_iconTop Results From Across the Web

Flutter Alarm Manager Missing Plugin Exception
I'm the main maintainer of the android_alarm_manager plugin. Assuming this isn't a brand new project created on top of Flutter 1.12, you can't...
Read more >
[Solved]-Flutter Alarm Manager Missing Plugin Exception-Flutter
I'm using Flutter v1.12 and I had the MissingPluginException yet. I solve my problem, registering SharedPreferences in my Application class:
Read more >
Schedule alarms - Android Developers
If a feature in your app requires a higher time precision, use exact alarms instead. Deliver a repeating alarm at roughly regular intervals....
Read more >
android_alarm_manager - Dart API docs - Pub.dev
A Flutter plugin for accessing the Android AlarmManager service, and running Dart code in the background when alarms fire.
Read more >
FlutterのPluginをほかのPlugin のMethodCallで使用した場合に ...
MissingPluginException When calling external packages from method call ... Flutter plugin for accessing the Android AlarmManager service, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found