FlutterLocalNotificationでプッシュ通知

概要

Flutterでプッシュ通知を実装するには、flutter_local_notificationsパッケージを使用する。

別の方法AwesomeNotificationでプッシュ通知

インストール

まず、パッケージをインストールする。

Info

flutter pub add flutter_local_notifications

権限

android/app/src/main/AndroidManifest.xmlへ以下を記述する。

<application>
	<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
	<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
		<intent-filter>
			<action android:name="android.intent.action.BOOT_COMPLETED"/>
			<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
			<action android:name="android.intent.action.QUICKBOOT_POWERON" />
			<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
		</intent-filter>
	</receiver>
</application>
 
#追加 端末が起動されたときに通知を受ける権限を要求する 
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
 
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
 
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
	

権限要求を使用して通知の権限要求をユーザに求める。

import 'package:permission_handler/permission_handler.dart';
 
class PermissionManager{
	Future<void> requsestNotifyPermission() async {
		PermissionStatus status = await Permission.notification.request();
	}
}

オブジェクト初期化

Androidは通知に使用するアイコンに初期化が必要である。
通知チャネルの概念が存在するので、NotificationDetailsに設定を渡す必要がある。

Info

通知チャネルとはこういうもの。
ユーザがそれぞれの通知を無効化などすることができる機能である。

以下のコードはそれを設定している。

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
 
Future<void> notify() {
  final flnp = FlutterLocalNotificationsPlugin();
  return flnp.initialize(
    InitializationSettings(
      android: AndroidInitializationSettings('@mipmap/ic_launcher'),
    ),
  ).then((_) => flnp.show(0, 'title', 'body', NotificationDetails(
    android: AndroidNotificationDetails(
      'channel_id',
      'channel_name',
      channelDescription: 'channel_description',
    ),
  )));
}

android: AndroidInitializationSettings('@mipmap/ic_launcher'),ではandroid/app/src/main/res/drawable以下の画像パス(拡張子なしのファイル名)を入れるとアイコンとして設定される。

ほとんどの場合以下のコードで初期化することができる。

import 'package:flutter_local_notifications/flutter_local_notifications.dart';  
  
class NotificationService {  
	final FlutterLocalNotificationsPlugin notificationsPlugin =  
		FlutterLocalNotificationsPlugin();  
	  
	Future<void> initNotification() async {  
	AndroidInitializationSettings initializationSettingsAndroid =  
		const AndroidInitializationSettings('flutter_logo');  
	  
	var initializationSettingsIOS = DarwinInitializationSettings(  
		requestAlertPermission: true,  
		requestBadgePermission: true,  
		requestSoundPermission: true,  
		onDidReceiveLocalNotification:  
			(int id, String? title, String? body, String? payload) async {}
	;  
	  
	var initializationSettings = InitializationSettings(  
		android: initializationSettingsAndroid, iOS: initializationSettingsIOS);  
		await notificationsPlugin.initialize(initializationSettings,  
		onDidReceiveNotificationResponse:  
			(NotificationResponse notificationResponse) async {});  
	}  
}

バナー通知

バナーを出す場合は、以下のようにコードを変更する。

  flnp.show(0, 'title', 'body', NotificationDetails(
    android: AndroidNotificationDetails(
      'channel_id',
      'channel_name',
      'channel_description',
+     importance: Importance.high,
+     priority: Priority.high,
    ),
  ))

指定時間に毎回通知

まず、時間をTZTimeZoneに直すプログラムを書く。

時間をTZDateTimeへ変換

以下のコードは時間(hour)と分(minutes)からTZDateTimeインスタンスを生成するコードである。

tz.TZDateTime _convertTime(int hour, int minutes) {
  final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
  tz.TZDateTime scheduleDate = tz.TZDateTime(
    tz.local,
    now.year,
    now.month,
    now.day,
    hour,
    minutes,
  );
  if (scheduleDate.isBefore(now)) {
    scheduleDate = scheduleDate.add(const Duration(days: 1));
  }
  return scheduleDate;
}
元記事へのリンク

そして、zonedScheduleメソッドで定期実行する。

// 毎週同じ時刻に通知(バックグラウンドも可)
await flnp.zonedSchedule(
	ここに通知ID,
	title,
	bodyText,
	_convertTime(10, 10),
	NotificationDetails(
		android: AndroidNotificationDetails(
			title,
			bodyText,
			importance: Importance.high,
			priority: Priority.high,
		),
	),
	uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime
);

よく使用するのは、idtitlebodyscheduledDatenotificationDetailsuiLocalNotificationDateInterpretationである。

id

idは通知のIDを登録する。
これは通知IDの識別や通知登録の削除に使用される。

title、body

titlebodyはユーザのAndroidの設定画面から通知のONOFFなどを設定する際に表示されるもの

scheduledDate

scheduledDateTimeZoneを使用していつ通知を行うかを制御するものである。

notificationDetails

notificationDetailsには、AndroidやiOSのネイティブの通知の設定を行う。
androidの場合は、

NotificationDetails(
	android: AndroidNotificationDetails(
		notify.title,
		notify.bodyText,
		importance: Importance.high,
		priority: Priority.high,
	),
), 

ここにタイトルやボディテキストを設定する。
優先度や重要度設定も可能。

uiLocalNotificationDateInterpretation

uiLocalNotificationDateInterpretationUiLocalNotificationDateInterpretationの値を渡す。

uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime

これは絶対時間を使用するもの
relativeTimeZoneを使用した場合はユーザのタイムゾーンに沿って通知をスケジュールする。

通知の繰り返す設定

matchDateTimeComponents: DateTimeComponents.time 。
これを設定すると、設定した日付時刻には1回めに通知され、2回目以降は同じ時間に繰り返させることができる。

DateTimeComponentsは、dayOfWeekAndTime dayOfMonthAndTime dateAndTime があり、dayOfWeekAndTimeなら、2回目以降、同じ曜日の同じ時間に繰り返すことができる。

通知の解除

通地の解除には、cancelメソッドを使用する。
引き数に通知IDをとる。

await flutterLocalNotificationsPlugin.cancel(0);

全てを解除するにはcancelALlを使用する。

await flutterLocalNotificationPlugin.cancelAll();