準備
AndroidManifest.xml
公式ドキュメント[1]にある通り「android/app/src/main/AndroidManifest.xml」に変更をする。
<manifest ~> <!-- 追加(1) --> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <!-- For apps with targetSDK=31 (Android 12) --> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <!-- (1)はここまで --> <application ~> <!-- 追加(2) --> <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" android:exported="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <!-- (2)はここまで --> <!-- 以下略 -->
pubspec.yaml
- 「android_alarm_manager_plus」を追加します(バージョンは現時点での最新版)。
dependencies: android_alarm_manager_plus: ^3.0.3
デモアプリ
ソースコード
import 'package:flutter/material.dart'; import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); //ウィジェット関連の初期化処理 AndroidAlarmManager.initialize(); //初期化 runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { // 現在時刻を表示 static Future<void> displayTime() async { print('now = ${DateTime.now()}'); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), body: Center( child: Column( children: <Widget>[ ElevatedButton( onPressed: () async { print('10秒後に現在時刻を表示(Schedule OneShot At)'); await AndroidAlarmManager.oneShotAt( DateTime.now().add(Duration(seconds: 10)), 0, displayTime ); }, child: const Text('Schedule OneShot At'), ), ElevatedButton( onPressed: () async { print('5秒後に現在時刻を表示(Schedule OneShot Alarm)'); await AndroidAlarmManager.oneShot( const Duration(seconds: 5), 1, displayTime, ); }, child: const Text('Schedule OneShot Alarm'), ), ElevatedButton( onPressed: () async { print('1分毎に現在時刻を表示(periodic)'); await AndroidAlarmManager.periodic( const Duration(minutes: 1), // const Duration(seconds: 10), 2, displayTime, // startAt: DateTime.now(), // exact: true ); }, child: const Text('periodic'), ), ] ) ), ); } }
解説
初期化処理
- AndroidAlarmManagerの初期化処理。
- これをせずにAndroidAlarmManagerの処理をしても動作するが、初期化⇒処理という順になるので数秒処理が遅く呼び出されるかも?
AndroidAlarmManager.initialize();
指定時刻に呼び出し(oneShotAt)
- デモアプリだと現在時刻から10秒後に処理をします。
- displayTimeは呼び出したい処理。
// printHelloを表示 static Future<void> displayTime() async { print('now = ${DateTime.now()}'); } //略 await AndroidAlarmManager.oneShotAt( DateTime.now().add(Duration(seconds: 10)), 0, displayTime );
指定時刻経過後に呼び出し(oneShot)
- デモアプリだと現在時刻から5秒後に処理をします。
await AndroidAlarmManager.oneShot( const Duration(seconds: 5), 1, displayTime, );
一定間隔で処理を呼び出す(periodic)
- デモアプリだと1分間隔で処理を呼び出します。
- 1秒とか間隔が短いと正しく動作しないこともありました。
await AndroidAlarmManager.periodic( const Duration(minutes: 1), 2, displayTime, );
キャンセル(periodic)
- 上記で割り当てたアラームをid指定で削除できます。
- 例:id=0のアラームを削除
await AndroidAlarmManager.cancel(0);