Flutterで毎朝8時に飛ぶローカル通知を実装する【OB-1アプデ】
以下の動画の要点だけをまとめたものを記事にしたいと思います。
動画ではあえて調べている過程なども載っけているので、むしろそこを見たい人は動画を見てください。
基本的なローカル通知の実装
基本的には以下のpackageのReadmeに書いてあることです。
Androidセットアップ
android/app/build.gradle
に必要なものを追加します。
android {
defaultConfig {
multiDexEnabled true
}
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation 'androidx.window:window:1.0.0'
implementation 'androidx.window:window-java:1.0.0'
}
android/build.gradle
にも必要なものを追加します。
buildscript {
...
dependencies {
classpath 'com.android.tools.build:gradle:4.2.2'
...
}
iOSセットアップ
AppDelegate.swift
に以下を追加します。
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
package追加
以下のコマンドを叩いてpackageを追加します。
flutter pub add flutter_local_notifications
通知の許可をとる
iOSとAndroidのものをそのまま全部張っちゃいます。
厳密にいうと、設定は色々変えれますが、一旦動かすという意味ではほぼコピーでいいと思います。
Future<void> _requestPermissions() async {
if (Platform.isIOS || Platform.isMacOS) {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
MacOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
} else if (Platform.isAndroid) {
final AndroidFlutterLocalNotificationsPlugin? androidImplementation =
flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>();
await androidImplementation?.requestPermission();
}
}
スケジュール通知を作成
まず、tzを定義しときましょう。
timezoneのpackageはflutter_local_notificationsにDependenciesとして入っています。
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
次に具体的なスケジュール通知。
Future<void> _scheduleDaily8AMNotification() async {
await flutterLocalNotificationsPlugin.zonedSchedule(
0,
'OB-1',
'本日の顔を撮影をしましょう',
_nextInstanceOf8AM(),
const NotificationDetails(
android: AndroidNotificationDetails(
'ob-1-face-daily',
'ob-1-face-daily',
channelDescription: 'Face photo notification',
),
iOS: DarwinNotificationDetails(
badgeNumber: 1,
),
),
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true,
);
}
// 1回目に通知を飛ばす時間の作成
tz.TZDateTime _nextInstanceOf8AM() {
final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
tz.TZDateTime scheduledDate =
tz.TZDateTime(tz.local, now.year, now.month, now.day, 8);
if (scheduledDate.isBefore(now)) {
scheduledDate = scheduledDate.add(const Duration(days: 1));
}
return scheduledDate;
}
毎日繰り返す設定
matchDateTimeComponents: DateTimeComponents.time
が魔法の1行です。これを設定すると、設定した日付時刻には1回めに通知され、2回目以降は同じ時間に繰り返させることができます。
DateTimeComponentsは、dayOfWeekAndTime
dayOfMonthAndTime
dateAndTime
があって、dayOfWeekAndTimeなら、2回目以降、同じ曜日の同じ時間に繰り返したりできます。
Future<void> _scheduleDaily8AMNotification() async {
await flutterLocalNotificationsPlugin.zonedSchedule(
0,
'OB-1',
'本日の顔を撮影をしましょう',
_nextInstanceOf8AM(),
const NotificationDetails(
android: AndroidNotificationDetails(
'ob-1-face-daily',
'ob-1-face-daily',
channelDescription: 'Face photo notification',
),
iOS: DarwinNotificationDetails(
badgeNumber: 1,
),
),
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
+ matchDateTimeComponents: DateTimeComponents.time,
androidAllowWhileIdle: true,
);
}
通知をオフにする
通知を設定でオフにするための実装です。このへんは、OB-1の独自のやり方なので、気になる方は動画を見てみてください。
- 処理の共通化
- enumで安全なコードにする
- shared_preferenceに保存
↑などを動画では解説しています。
追記
細かい部分で抜けている処理があったので追記です。
日本時間に修正
以下をmain.dartに書いておきましょう。これないと、ロンドン標準時刻になっちゃいました。
tz.initializeTimeZones();
tz.setLocalLocation(tz.getLocation("Asia/Tokyo"));
バッジをリセット
https://pub.dev/packages/flutter_app_badger を入れて、以下のコードを叩くだけでバッジを消せます。
FlutterAppBadger.removeBadge();
まとめ
以上です。
↓アプリのコードはこちら(Flutter大学に入ってる人は見れます)
Discussion