Fluttter Alarm Manager Missing Plugin Exception

1,095

Solution 1

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 use other plugins from the background without jumping through a couple of more hoops.

When you're executing an alarm callback, that callback is actually running on another Isolate (basically Dart's version of a thread which doesn't share memory with other threads). When Flutter starts the main isolate for the application, it needs to register all of the plugins in the application with that isolate so all of the plugins can be initialized and ready to handle messages from Dart code. This is done at startup when Flutter calls GeneratedPluginRegistrant.registerWith, an auto-generated method which handles plugin registration for the application. However, this isn't done automatically in the background since the isolate spawned by the android_alarm_manager plugin doesn't go through the same initialization as the main isolate would since it can be spawned at any time to handle an alarm event, so the plugin spawning the isolate is responsible for registering all of the plugins.

TL;DR: You'll have to follow a couple of steps listed in the README for the android_alarm_manager plugin here, but basically you'll need to do the following:

  • Add a custom implementation for Application which extends FlutterApplication and implements PluginRegistrantCallback. In onCreate, you'll want to call AlarmService.setPluginRegistrant(this). Finally, you'll want to implement void registerWith(PluginRegistry registry) and call GeneratedPluginRegistrant.registerWith(registry).

When you're done, your Application class should look something like this:

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

  // This method is called by AlarmService to register the plugins with the
  // isolate it spawns to execute code in the background.
  @Override
  public void registerWith(PluginRegistry registry) {
    // GeneratedPluginRegistrant is auto-generated and contains all the plugin
    // registration code.
    GeneratedPluginRegistrant.registerWith(registry);
  }
}
  • Once your Application class is implemented, you'll also need to update AndroidManifest.xml to use your custom Application as the entrypoint:
   <application
        android:name=".Application"
        ...

Once you've done that, you should be able to use other plugins from isolates spawned by package:android_alarm_manager. The one exception is if you've created a brand new Flutter application since the release of Flutter 1.12, in which case the newest version of the plugin should do this automatically for you. If that's the case, something's likely broken and you'll want to file an issue on GitHub.

Solution 2

I'm using Flutter v1.12 and I had the MissingPluginException yet. I solve my problem, registering SharedPreferences in my Application class:

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.androidalarmmanager.AlarmService
import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin


class Application : FlutterApplication(), PluginRegistrantCallback {
    override fun onCreate() {
        super.onCreate()
        AlarmService.setPluginRegistrant(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
        //Register sharedPreferences here        
        SharedPreferencesPlugin.registerWith(registry?.registrarFor(
        "io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));
    }
}
Share:
1,095
Michael Johnston
Author by

Michael Johnston

Updated on December 16, 2022

Comments

  • Michael Johnston
    Michael Johnston over 1 year

    I'm having trouble setting up a daily task to complete certain functions. I've managed to get android_alarm_manager to work, currently have it set to printing a message in the log every minute for testing purposes but will have it set daily when finished. Below is my code:

    void printHello() async{
      final DateTime now = DateTime.now();
      final int isolateId = Isolate.current.hashCode;
      print("[$now] Hello, world! isolate=${isolateId} function='$printHello'");
    
      int myValue = await getData();
    
      print("Test Value: $myValue");
    }
    
    Future<int> getData() async{
      SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
    
      return sharedPreferences.getInt("testInt");
    }
    
    main() async {
      WidgetsFlutterBinding.ensureInitialized();
      final int helloAlarmID = 0;
      await AndroidAlarmManager.initialize();
      runApp(MyApp());
      await AndroidAlarmManager.periodic(const Duration(minutes: 1), helloAlarmID, printHello);
    }
    

    When the alarm fires I get the working print message like in the example and the error like this

    I/flutter (22910): [2019-12-21 13:34:09.526343] Hello, world! isolate=957159586 function='Closure: () => void from Function 'printHello': static.'
    E/flutter (22910): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)
    E/flutter (22910): #0      getData (package:my_jungle_2/main.dart:34:41)
    E/flutter (22910): <asynchronous suspension>
    E/flutter (22910): #1      printHello (package:my_jungle_2/main.dart:28:23)
    E/flutter (22910): #2      _alarmManagerCallbackDispatcher.<anonymous closure> (package:android_alarm_manager/android_alarm_manager.dart:43:14)
    E/flutter (22910): #3      MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:402:55)
    E/flutter (22910): #4      MethodChannel.setMethodCallHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:370:54)
    E/flutter (22910): #5      _DefaultBinaryMessenger.handlePlatformMessage (package:flutter/src/services/binding.dart:200:33)
    E/flutter (22910): #6      _invoke3.<anonymous closure> (dart:ui/hooks.dart:303:15)
    E/flutter (22910): #7      _rootRun (dart:async/zone.dart:1126:13)
    E/flutter (22910): #8      _CustomZone.run (dart:async/zone.dart:1023:19)
    E/flutter (22910): #9      _CustomZone.runGuarded (dart:async/zone.dart:925:7)
    E/flutter (22910): #10     _invoke3 (dart:ui/hooks.dart:302:10)
    E/flutter (22910): #11     _dispatchPlatformMessage (dart:ui/hooks.dart:162:5)
    

    I am still a novice at Android and Flutter and am struggling to understand how I give the alarm manager the plugins I need it to use.

    Are you even able to give the Alarm Manager plugins like Shared Preferences?

    Thank you in advance for any help on clearing this up for me. Apologies if I haven't understood how alarm manager is meant to work correctly.

  • Michael Johnston
    Michael Johnston over 4 years
    Thank you for this, looks like it will solve the problems I've been having. Annoyingly won't be able to get back to my pc until after Christmas now to try it out.
  • Deepak Rana
    Deepak Rana about 4 years
    @Ben i am using v1.12 and still getting the same issue