21

Error I have installed the Android Alarm Manager plugin in my new Flutter app. I tried using the example code of Plugin, but it gives an error in console.

Please suggest how to make the Android Alarm Manager plugin work. How do I integrate Dart's android_alarm_manager to the app so that users get alarm when the time they picked in the schedule reaches?

I use the code from this link: https://github.com/flutter/plugins/tree/master/packages/android_alarm_manager

main.dart:

import 'dart:isolate';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';
    
void printHello() {
  final DateTime now = DateTime.now();
  final int isolateId = Isolate.current.hashCode;
  print("[$now] Hello, world! isolate=${isolateId} function='$printHello'");
}

void main() async {
  final int helloAlarmID = 0;
  await AndroidAlarmManager.initialize();
  runApp(MaterialApp(home: Application()));
  await AndroidAlarmManager.periodic(const Duration(minutes: 1), helloAlarmID, printHello);
}

class Application extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(),
    );
  }
}

Application.java:

package io.flutter.plugins.androidalarmmanagerexample;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
    
public class Application extends FlutterApplication implements PluginRegistrantCallback {
    @Override
    public void onCreate() {
        super.onCreate();
    
        AlarmService.setPluginRegistrant(this);
    }

    @Override
    public void registerWith(PluginRegistry registry) {
        GeneratedPluginRegistrant.registerWith(registry);
    }
}               

When I run this code it prints the following error to console:

E/flutter ( 6831): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(error, Attempt to invoke interface method 'void io.flutter.plugin.common.PluginRegistry$PluginRegistrantCallback.registerWith(io.flutter.plugin.common.PluginRegistry)' on a null object reference, null)
E/flutter ( 6831): #0      JSONMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:149:7)
E/flutter ( 6831): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:33)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #2      AndroidAlarmManager.initialize (package:android_alarm_manager/android_alarm_manager.dart:76:10)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #3      main (package:alarmdemo/main.dart:12:29)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #4      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter ( 6831): #5      _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6831): #6      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6831): #7      _runZoned (dart:async/zone.dart:1516:10)
E/flutter ( 6831): #8      runZoned (dart:async/zone.dart:1500:12)
E/flutter ( 6831): #9      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter ( 6831): #10     _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
E/flutter ( 6831): #11     _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
E/flutter ( 6831): 
E/flutter ( 6831): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: MissingPluginException(No implementation found for method AlarmService.initialized on channel plugins.flutter.io/android_alarm_manager_background)
E/flutter ( 6831): #0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:300:7)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #1      _alarmManagerCallbackDispatcher (package:android_alarm_manager/android_alarm_manager.dart:49:12)
E/flutter ( 6831): #2      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter ( 6831): #3      _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6831): #4      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6831): #5      _runZoned (dart:async/zone.dart:1516:10)
E/flutter ( 6831): #6      runZoned (dart:async/zone.dart:1500:12)
E/flutter ( 6831): #7      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter ( 6831): #8      _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
E/flutter ( 6831): #9      _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
E/flutter ( 6831): 

This is my updated code:

main.dart:

void printHello() {
  final DateTime now = new DateTime.now();
  final int isolateId = Isolate.current.hashCode;
  print("[$now] Hello, world! isolate=${isolateId} 
      function='$printHello'");
}

void main() async {
  runApp(MaterialApp(home: Application()));
}
    
class Application extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Center(
          child: RaisedButton(
            child: Text('Hello'),
            onPressed: () {
              runAlarm();
            },
          ),
        ),
      ),
    );
  }

  void runAlarm() {
    AndroidAlarmManager.oneShot(
      Duration(seconds: 10),
      0,
      printHello,
      wakeup: true,
    ).then((val) => print(val));
  }

  static void alarmTest() {
    print("test");
  }
}

It does not print any error to console but it prints the following two lines:

E/AlarmService(11943): Fatal: failed to find callback
I/AlarmService(11943): AlarmService has not yet started.

I also tried initializing the alarm manager but it prints an error to console:

void runAlarm() {
  AndroidAlarmManager.periodic(
    Duration(seconds: 10),
    0,
    printHello,
    wakeup: true,
  ).then((val) => print(val)).catchError((e) {
    print(e);
  });
}

Error:

E/flutter ( 6831): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(error, Attempt to invoke interface method 'void io.flutter.plugin.common.PluginRegistry$PluginRegistrantCallback.registerWith(io.flutter.plugin.common.PluginRegistry)' on a null object reference, null)
E/flutter ( 6831): #0      JSONMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:149:7)
E/flutter ( 6831): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:33)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #2      AndroidAlarmManager.initialize (package:android_alarm_manager/android_alarm_manager.dart:76:10)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #3      main (package:alarmdemo/main.dart:12:29)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #4      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter ( 6831): #5      _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6831): #6      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6831): #7      _runZoned (dart:async/zone.dart:1516:10)
E/flutter ( 6831): #8      runZoned (dart:async/zone.dart:1500:12)
E/flutter ( 6831): #9      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter ( 6831): #10     _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
E/flutter ( 6831): #11     _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
E/flutter ( 6831): 
E/flutter ( 6831): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: MissingPluginException(No implementation found for method AlarmService.initialized on channel plugins.flutter.io/android_alarm_manager_background)
E/flutter ( 6831): #0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:300:7)
E/flutter ( 6831): <asynchronous suspension>
E/flutter ( 6831): #1      _alarmManagerCallbackDispatcher (package:android_alarm_manager/android_alarm_manager.dart:49:12)
E/flutter ( 6831): #2      _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)
E/flutter ( 6831): #3      _rootRun (dart:async/zone.dart:1124:13)
E/flutter ( 6831): #4      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter ( 6831): #5      _runZoned (dart:async/zone.dart:1516:10)
E/flutter ( 6831): #6      runZoned (dart:async/zone.dart:1500:12)
E/flutter ( 6831): #7      _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)
E/flutter ( 6831): #8      _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)
E/flutter ( 6831): #9      _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
E/flutter ( 6831): 

enter image description here

Samplasion
  • 527
  • 4
  • 17
Manpreet Kaur
  • 396
  • 1
  • 2
  • 8

6 Answers6

15

I've finally fixed this issue myself, after struggling for a couple of hours (but felt a lot longer!). The breakthrough came when I actually cloned the Flutter Plugins Github repository that contains android_alarm_manager and poked around the example code and looked at how it was laid out in an IDE, rather than looking at isolated files online.

The Readme is not very clear on what exactly to do, if you're not versed in Android Java development, but it becomes clear when you look at the working example code.

You need to drop in the Application.java file they give you in the example directory into your actual project, in the same folder as your existing MainActivity.java file. The contents should look like this:

package io.flutter.plugins.androidalarmmanagerexample;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;

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

  @Override
  public void registerWith(PluginRegistry registry) {
    GeneratedPluginRegistrant.registerWith(registry);
  }
}

As for where you need to put this file, their example it looks like this, but yours is probably in something like <your project dir>/android/app/src/main/java/com/example/<your project name>:

The Application.java file goes in the same folder as your MainActivity.java

After doing this, you must update the package name on the first line of Application.java from package io.flutter.plugins.androidalarmmanagerexample; to match whatever package your project uses (see the first line of your existing MainActivity.java). If you don't do this, gradle doesn't find it and nothing works!

You can now follow the advice in the Readme, adding in the permissions and etc:

After importing this plugin to your project as usual, add the following to your AndroidManifest.xml within the <manifest></manifest> tags:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

Next, within the <application></application> tags, add:

<service
    android:name="io.flutter.plugins.androidalarmmanager.AlarmService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="false"/>
<receiver
    android:name="io.flutter.plugins.androidalarmmanager.AlarmBroadcastReceiver"
    android:exported="false"/>
<receiver
    android:name="io.flutter.plugins.androidalarmmanager.RebootBroadcastReceiver"
    android:enabled="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"></action>
    </intent-filter>
</receiver>

The last part is the part that most confused me. It sounds like they're being very vague, but if you did everything else exactly right earlier, it's actually precisely what you need to do.

Which must be reflected in the application's AndroidManifest.xml. E.g.:

    <application
        android:name=".Application"
        ...

Simply change your android:name to .Application, which means it will now utilise that Application.java we added previously.

That's it! Hopefully you can now run your app.

pipedreambomb
  • 3,711
  • 1
  • 22
  • 18
  • Thanks for your response. I Try this answer but i am getting the errors on alarm services which i defined in Application.java file. I also share error as well as code of Application.java class. – Manpreet Kaur Apr 25 '19 at 04:53
  • Sorry, I don't know how to help you. I was lucky to get it working for myself, because I don't really understand much about Android development! Edit, actually, looking at your screenshot, the fact that `AlarmService` is in red looks like it's not importing it, perhaps because it's not installed. I'd start by looking into that. – pipedreambomb Apr 26 '19 at 12:01
  • It would be better to include the Application.java code in the answer rather than refer out to it. I didn't realise the significance till I saw the actual code in Sen Sokha's answer. Maybe also change the name to MyApplication to make the link clearer, i.e. it's your choice of name. – Bill99 May 19 '19 at 10:24
  • @Bill99 I've added the contents of the Application.java file to my answer as you suggested. I'm leaving the name the same as in their documentation, particularly since I don't know enough about it myself to reliably going around renaming things I don't need to! Bit of cargo cult programming here, but it works. – pipedreambomb May 24 '19 at 15:14
  • Cannot resolve symbol 'AlarmService'. Cannot resolve 'androidalarmmanager' in the import statement. Wat do? – TimSim Jul 02 '19 at 13:19
5

Problem: Unhandled Exception: MissingPluginException(No implementation found for method AlarmService.initialized on channel plugins.flutter.io/android_alarm_manager_background)

Reason: Alarm callbacks will need access to other Flutter plugins, including the alarm manager plugin itself, it is necessary to teach the background service how to initialize plugins. Since AlarmManager uses separate isolate, any plugin that is used in scheduled code needs to be initialized for AlarmManager separately.

Solution: Register alarm manager plugin itself in Application.java as below;(resolved official flutter repo issues #21969)

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;
import io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin;

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

  @Override
  public void registerWith(PluginRegistry registry) {
    // GeneratedPluginRegistrant.registerWith(registry);
    AndroidAlarmManagerPlugin.registerWith(registry.registrarFor("io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin"));
  }
}

*Note: if you have used another plugins in your project, You would have also add it all into your Application.java file.

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

  }

  @Override
  public void registerWith(PluginRegistry registry) {
    // GeneratedPluginRegistrant.registerWith(registry);

    //add AndroidAlarmManagerPlugin plugin register  if you work with arlarm
    AndroidAlarmManagerPlugin.registerWith(registry.registrarFor("io.flutter.plugins.androidalarmmanager.AndroidAlarmManagerPlugin"));

    //add PathProviderPlugin plugin register  if you work with Access Path Device
    PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));

    //add SqflitePlugin plugin register  if you work with sqflite
    SqflitePlugin.registerWith(registry.registrarFor("com.tekartik.sqflite.SqflitePlugin"));

    //add PermissionHandlerPlugin plugin register  if you work with permission handler
    PermissionHandlerPlugin.registerWith(registry.registrarFor("com.baseflow.permissionhandler.PermissionHandlerPlugin"));

    //add SharedPreferencesPlugin plugin register  if you work with share preferences
    SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));

    // something else...

  }
}
Sen Sokha
  • 1,784
  • 16
  • 16
  • I had an issue with `GeneratedPluginRegistrant.registerWith(registry);` as some of my plugins require activity context. `AndroidAlarmManagerPlugin.registerWith ` fixed my issue. – kdy Sep 05 '19 at 08:29
  • when I tried out this I am getting issues with sharedpreference, In flutter code I am using sharedpreference, gets an error no implementation found – shahana kareen Dec 04 '19 at 06:33
  • @shahanakareen please try, `flutter clean & flutter run` again. – Sen Sokha Dec 04 '19 at 08:47
  • if you still have errors please mentions all channel plugin what you used in `Application.java` as below; `SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));` – Sen Sokha Dec 04 '19 at 09:05
2

You did not initialize the alarm object and callback handler.

await AndroidAlarmManager.initialize();

What happens is when the app start running this:

 void main() async {
    runApp(MaterialApp(home: Application()));
 }

The app just run and draw the UI for you. Once you click the button, the following method is called:

AndroidAlarmManager.oneShot(
   Duration(seconds: 10),
   0,
   printHello,
   wakeup: true,
)

This function is simply scheduling a callback after the delay time specified. This would fail because the Callback handler is not registered. Meaning, after the timeout, it couldn't find 'anyone' responsible to run the 'printHello'.

edit:

You also need to override a method to help plugin register themselves on create.

Create a new file like below:

yourapprootfolder/android/app/src/main/java/io/flutter/plugins/androidalarmmanagerexample/Application.java

Inside the .java file, put this:

package io.flutter.plugins.androidalarmmanagerexample;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;

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

  @Override
  public void registerWith(PluginRegistry registry) {
    GeneratedPluginRegistrant.registerWith(registry);
  }
}

or in Kt files:

package io.flutter.plugins.androidalarmmanagerexample;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.androidalarmmanager.AlarmService;

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

      override fun registerWith(registry: PluginRegistry) {
        GeneratedPluginRegistrant.registerWith(registry);
      }
}
0xCCY
  • 555
  • 2
  • 10
  • Thanks for your answer.I update my code but still it gives error. – Manpreet Kaur Feb 26 '19 at 05:46
  • Which is a new error, I suppose. Updated answer. Don't just copy a plugin blindly and expect it to work, maybe try to understand it. – 0xCCY Feb 26 '19 at 06:21
  • I use this code before. As you mention this code is put in Application.java class but that file gives error and it does not pick some AlarmService. and how I change the android:name in manifest file? -@CheunYee – Manpreet Kaur Feb 26 '19 at 06:45
  • Application java has to be put into the build folder of Android, it is not going to be compiled as Flutter. This plugin is a bit complicated as it needs stuff to be called at background. Manifest file can be found in android/src/main. – 0xCCY Feb 26 '19 at 06:56
  • I update my question with screenshot where it gives an error on AlarmService and says that AlarmService is unresolved reference-@CheunYee – Manpreet Kaur Feb 26 '19 at 07:29
  • Because the example provided is in Java but you are using it in Kotlin...updating my answer shortly. – 0xCCY Feb 26 '19 at 07:48
  • I've created the .java file, but I still don't understand how to reference it from my manifest file. I'm still learning Flutter with VS Code and I have no idea how this Android stuff in Android Studio is supposed to work. The idea is usually that it generates it all for me. – pipedreambomb Apr 24 '19 at 14:26
1

Are you referencing you Application in you AndroidManifest.xml? BTW (I would use a different name to not have any confusion with Android's Application, for example MyFlutterApplication).

Notice in the documentation of the plugin it states:

Which must be reflected in the application's AndroidManifest.xml. E.g.:

<application
    android:name=".Application"
    ...

For more information see Android Developers element documentation.

Xavier Rubio Jansana
  • 6,388
  • 1
  • 27
  • 50
1

I had the same problem. Simply open the android project. Perform a Gradle sync. Next, do a "build -> clean project" and "build -> rebuild project".

Robin Dijkhof
  • 18,665
  • 11
  • 65
  • 116
0

If you are developing this app for android only then you can create native foreground/background service which runs for every given interval of time. Then using the platform channel you can call the service from dart either on button tap if you want it run every time on certain condition or using shared prefrence call the native service from initState() in your homepage. As you might know once the native service is started it will invoke itself after every given interval of time(like minute or 24hours).

Harsha pulikollu
  • 2,386
  • 15
  • 28