You are currently viewing Flutter AlarmManager Plus Example

Flutter AlarmManager Plus Example

With the previous Flutter AlarmManager package deprecated, it has been now recommended that you use the Flutter AlarmManager Plus, which this tutorial covers. You can use this package to create an Alarm or Scheduling application with Flutter Android.

flutter_alarm_manager_plus is a Flutter plugin for accessing the Android AlarmManager service, and running Dart code in the background when alarms fire.

Note that this plugin supports only Android.

Here is how you use it.

Step 1: Install it

Start by installing the flutter_alarm_manager_plus by declaring the following in your pubspec.yaml:

dependencies:
  android_alarm_manager_plus: ^2.0.2

Then sync to fetch it.

You can also fetch it by executing the following in your terminal:

flutter pub add android_alarm_manager_plus

Step 2: Add Permissions

In your AndroidManifest.xml add the following permissions:

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

Then within the same AndroidManifest.xml, but inside the <application>..</application> tags, add the following:

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

Step 3: Import

Then import it into your project:

import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart';

Step 4: Write Code

For example, let's say you want to run a printHellow() function that greets the user every minute:

Here is the defintion of the method:

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

Then here is the main function:

main() async {
  // Be sure to add this line if initialize() call happens before runApp()
  WidgetsFlutterBinding.ensureInitialized();
  await AndroidAlarmManager.initialize();
  runApp(...);
  final int helloAlarmID = 0;
  await AndroidAlarmManager.periodic(const Duration(minutes: 1), helloAlarmID, printHello);
}

printHello will then run (roughly) every minute, even if the main app ends. However, printHello will not run in the same isolate as the main application. Unlike threads, isolates do not share memory and communication between isolates must be done via message passing

Full Example

  1. Start by installing the package as has been described.
  2. Add permissions as has been described.
  3. Replace your main.dart with the following code:

main.dart

import 'dart:isolate';
import 'dart:math';
import 'dart:ui';
import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/material.dart';
/// The [SharedPreferences] key to access the alarm fire count.
const String countKey = 'count';
/// The name associated with the UI isolate's [SendPort].
const String isolateName = 'isolate';
/// A port used to communicate from a background isolate to the UI isolate.
final ReceivePort port = ReceivePort();
/// Global [SharedPreferences] object.
SharedPreferences prefs;
Future<void> main() async {
  // ignore: todo
  // TODO(bkonyi): uncomment
  WidgetsFlutterBinding.ensureInitialized();
  // Register the UI isolate's SendPort to allow for communication from the
  // background isolate.
  IsolateNameServer.registerPortWithName(
    port.sendPort,
    isolateName,
  );
  prefs = await SharedPreferences.getInstance();
  if (!prefs.containsKey(countKey)) {
    await prefs.setInt(countKey, 0);
  }
  runApp(const AlarmManagerExampleApp());
}
/// Example app for Espresso plugin.
class AlarmManagerExampleApp extends StatelessWidget {
  const AlarmManagerExampleApp({Key key}) : super(key: key);
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: _AlarmHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class _AlarmHomePage extends StatefulWidget {
  const _AlarmHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _AlarmHomePageState createState() => _AlarmHomePageState();
}
class _AlarmHomePageState extends State<_AlarmHomePage> {
  int _counter = 0;
  @override
  void initState() {
    super.initState();
    AndroidAlarmManager.initialize();
    // Register for events from the background isolate. These messages will
    // always coincide with an alarm firing.
    port.listen((_) async => await _incrementCounter());
  }
  Future<void> _incrementCounter() async {
    print('Increment counter!');
    // Ensure we've loaded the updated count from the background isolate.
    await prefs.reload();
    setState(() {
      _counter++;
    });
  }
  // The background
  static SendPort uiSendPort;
  // The callback for our alarm
  static Future<void> callback() async {
    print('Alarm fired!');
    // Get the previous cached count and increment it.
    final prefs = await SharedPreferences.getInstance();
    final currentCount = prefs.getInt(countKey);
    await prefs.setInt(countKey, currentCount + 1);
    // This will be null if we're running in the background.
    uiSendPort ??= IsolateNameServer.lookupPortByName(isolateName);
    uiSendPort?.send(null);
  }
  @override
  Widget build(BuildContext context) {
    final textStyle = Theme.of(context).textTheme.headline4;
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Alarm fired $_counter times',
              style: textStyle,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Total alarms fired: ',
                  style: textStyle,
                ),
                Text(
                  prefs.getInt(countKey).toString(),
                  key: const ValueKey('BackgroundCountText'),
                  style: textStyle,
                ),
              ],
            ),
            ElevatedButton(
              key: const ValueKey('RegisterOneShotAlarm'),
              onPressed: () async {
                await AndroidAlarmManager.oneShot(
                  const Duration(seconds: 5),
                  // Ensure we have a unique alarm ID.
                  Random().nextInt(pow(2, 31)),
                  callback,
                  exact: true,
                  wakeup: true,
                );
              },
              child: const Text(
                'Schedule OneShot Alarm',
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Reference

Find the reference links below:

Number Link
1. Download Example
2. Read more

Example 2: Using android_alarm_manager package

This is an example using the now deprecated android_alarm_manager plugin.

android_alarm_manager is a Flutter plugin for accessing the Android AlarmManager service, and running Dart code in the background when alarms fire.

Step 1: Install android_alarm_manager

Go to your pubspec.yaml and add the android_alarm_manager as a dependency, as follows:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.3
  android_alarm_manager: ^0.4.5+14

Step 2: Add Permissions

Go to your /Android/app/src/main/AndroidManifest.xml and add the following two permissions:

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

Then within the same file, but inside the <application>..</application> tag, add the following:

        <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>

Step 4: Write Code

Go to your main.dart file and add the following imports:

import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';

Create an async main method as follows:

main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await AndroidAlarmManager.initialize();
  runApp(MyApp());
}

Extend the StatefulWidget:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

Here is the function that will be run periodically:

showprint() {
  print('alarm done');
}

Hereis the State class:

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: OutlineButton(
            child: Text('Alarm now'),
            onPressed: () {
              AndroidAlarmManager.oneShot(Duration(seconds: 3), 0, showprint);
            },
          ),
        ),
      ),
    );
  }
}

Here is the full code:

main.dart

import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';
main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await AndroidAlarmManager.initialize();
  runApp(MyApp());
}
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
showprint() {
  print('alarm done');
}
class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: OutlineButton(
            child: Text('Alarm now'),
            onPressed: () {
              AndroidAlarmManager.oneShot(Duration(seconds: 3), 0, showprint);
            },
          ),
        ),
      ),
    );
  }
}

Reference

Download the code here

Leave a Reply