[Flutter]Android用のPush通知を実装する

広告Flutter
2024年2月4日2024年4月11日

Firebase Cloud Messaging(以下FCM)を利用して、FlutterのAndroidアプリでプッシュ通知を受け取る機能を実装していきます。
アプリの状態がForeground・Backgroundで通知が表示されるようにします。

環境
  • Flutter 3.16.5
  • firebase_core: ^2.25.3
  • firebase_messaging: ^14.7.14
  • flutter_local_notifications: ^16.3.2
  • Android実機で検証

Firebaseの事前準備

公式を参考にアプリにFirebaseを追加して初期化します。 https://firebase.google.com/docs/flutter/setup?hl=ja&platform=ios

  • Firebase プロジェクトを作成する
  • Firebase プロジェクトに Android アプリを追加する
  • Flutterアプリで Firebase を初期化する

通知の設定

FCMプラグインをインストールする

flutter pub add firebase_messaging
pubspec.yaml
dependencies:
  firebase_messaging: ^14.7.14

FCMのトークンを取得する

main.dartに importします。

main.dart
import 'package:firebase_messaging/firebase_messaging.dart';

端末のトークンを取得する処理を追加します。

main.dart
void main() async {
	WidgetsFlutterBinding.ensureInitialized();
	
	await Firebase.initializeApp(
		options: DefaultFirebaseOptions.currentPlatform,
	);
	// --> 追加
	final fcmToken = await FirebaseMessaging.instance.getToken();
	debugPrint('FCM Token: $fcmToken');
	// <-- ここまで追加
	
	runApp(const MyApp());
}

アプリを起動し、コンソールに出力されるトークンを取得します。 

I/flutter ( 8665): FCM Token: fj0wJtdDSsqBRAKuhjjnfd:APA96*********m2CFapQxU2etz3Q6*********3GT2_mW3IbF6S_AL9CcWLzkxqGyJHI0o6*********8axj1tcv5GHzJpZxYFzYN4WzPwB2ZuN4F8m_sR6*********

プッシュ通知権限リクエスト

Android13 から Android でもプッシュ通知権限の要求が必要になりました。

Android で Firebase Cloud Messaging クライアント アプリを設定する

google.comgoogle.com

AndroidManifest.xmlにPOST_NOTIFICATIONS権限設定を追加します。

AndroidManifest.xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

権限リクエスト処理を追加します。

main.dart
void main() async {
  ・・・
  FirebaseMessaging.instance.requestPermission();

アプリを起動すると通知権限のリクエストが表示されます。
初回に許可しなかった場合、変更するには設定画面から許可する必要があります。

Android 通知権限リクエスト
Android 通知権限リクエスト

通知を受信する

アプリがBackground時にプッシュ通知を受け取る

Firebaseのコンソールから通知を送信します。

FirebaseのメニューからCloud Messagingを選択し、「最初のキャンペーンを作成」から通知の作成画面を開きます。 通知のタイトル・通知テキストを入力し、右側「デバイスのプレビュー」の「テストメッセージを送信」ボタンを押下します。

FCM 通知作成
FCM 通知作成

取得したトークンを追加・選択し、「テスト」ボタンを押下します。

FCM トークン入力
FCM トークン入力

アプリをBackgroundにした状態で送信するとプッシュ通知が届きます。

Android端末 通知表示
Android端末 通知表示

アプリがForegroundにある場合は別の設定が必要になります。

アプリがForeground時にプッシュ通知を受け取り表示する

アプリがForeground時にリモート通知で受けとったメッセージを通知表示します。 ローカル通知の機能を利用します。

Flutterプロジェクトにflutter_local_notificationパッケージをインストールします。

flutter pub add flutter_local_notifications
pubspec.yaml
dependencies:
	flutter_local_notifications: ^16.3.2

main.dartにインポートします。

main.dart
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

ローカル通知の処理を追加します。

main.dart
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
 
const AndroidNotificationChannel channel = AndroidNotificationChannel(
	'channel_id', // id
	'channel title', // title
	description: 'This channel is used for Info notifications.', // description
	importance: Importance.high,
);

メッセージを受信する処理を追加します。

main.dart
void main() async {
 ・・・
  // Foregroundでのメッセージ受信時の処理
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    print('Foregroundでメッセージを受信しました message: ${message.notification!.body}');
 
    RemoteNotification? notification = message.notification;
 
    if (notification != null) {
      flutterLocalNotificationsPlugin.show(
        notification.hashCode,
        notification.title,
        notification.body,
        NotificationDetails(
          android: AndroidNotificationDetails(
            channel.id,
            channel.name,
            channelDescription: channel.description,
            importance: Importance.high,
            icon: '@mipmap/ic_launcher',
          ),
        ),
      );
    }
  });

つまづいたところ

Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference メッセージ

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(error, Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference, null, java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference

AndroidNotificationDetailsでiconを指定していない状態で発生しました。

FlutterLocalNotificationsPluginのinitializeでアイコンを設定するか NotificationDetailsで個別にアイコンを指定することで解消しました。

FlutterLocalNotificationsPluginの場合

void main() async {
	・・・
  await flutterLocalNotificationsPlugin.initialize(
    const InitializationSettings(
        android: AndroidInitializationSettings('@mipmap/ic_launcher')),
  );

NotificationDetailsの場合

	NotificationDetails(
	  android: AndroidNotificationDetails(
		channel.id,
		channel.name,
		channelDescription: channel.description,
		importance: Importance.high,
		icon: '@mipmap/ic_launcher',  // <-- アイコン指定
	  ),
	),

Foreground時に通知が表示されない

無効なアイコン名を指定していたことが原因でした。

icon: 'launch_background', 

有効なアイコンに変更し、表示されるようになりました。(環境に合わせてください)

icon: '@mipmap/ic_launcher', 

参考

アプリの状態について

Flutter アプリでメッセージを受信する  |  Firebase Cloud Messaging

google.comgoogle.com

App Icons

Create app icons  |  Android Studio  |  Android Developers

Call on material icons with Compose or use Image Asset Studio, which helps you generate your own app icons from material icons, custom images, and text strings.android.comandroid.com
Create app icons  |  Android Studio  |  Android Developers