'Flutter Alarm Manager Missing Plugin Exception
I'm having trouble setting up a daily task to complete certain functions. I've managed to get android_alarm_manager to work, I currently, have it set to print 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 to use.
Are you even able to give the Alarm Manager plugins like Shared Preferences?
Thank you in advance for any help in clearing this up for me. Apologies if I haven't understood how the alarm manager is meant to work correctly.
Solution 1:[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 extendsFlutterApplication
and implementsPluginRegistrantCallback
. InonCreate
, you'll want to callAlarmService.setPluginRegistrant(this)
. Finally, you'll want to implementvoid registerWith(PluginRegistry registry)
and callGeneratedPluginRegistrant.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 updateAndroidManifest.xml
to use your customApplication
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:[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"));
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Ben Konyi |
Solution 2 | Javier Hinmel |