| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // ignore_for_file: public_member_api_docs |
| |
| import 'dart:isolate'; |
| import 'dart:math'; |
| import 'dart:ui'; |
| |
| import 'package:android_alarm_manager/android_alarm_manager.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 { |
| // 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(AlarmManagerExampleApp()); |
| } |
| |
| /// Example app for Espresso plugin. |
| class AlarmManagerExampleApp extends StatelessWidget { |
| // This widget is the root of your application. |
| @override |
| Widget build(BuildContext context) { |
| return MaterialApp( |
| title: 'Flutter Demo', |
| home: _AlarmHomePage(title: 'Flutter Demo Home Page'), |
| ); |
| } |
| } |
| |
| class _AlarmHomePage extends StatefulWidget { |
| _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(); |
| int 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) { |
| // TODO(jackson): This has been deprecated and should be replaced |
| // with `headline4` when it's available on all the versions of |
| // Flutter that we test. |
| // ignore: deprecated_member_use |
| final textStyle = Theme.of(context).textTheme.display1; |
| 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: ValueKey('BackgroundCountText'), |
| style: textStyle, |
| ), |
| ], |
| ), |
| RaisedButton( |
| child: Text( |
| 'Schedule OneShot Alarm', |
| ), |
| key: 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, |
| ); |
| }, |
| ), |
| ], |
| ), |
| ), |
| ); |
| } |
| } |