[Flutter]プッシュ通知を受信する

🚧

Firebase Cloud Messaging SDKの組み込みについて

KARTE SDKに関連する実装以外にも、プッシュ通知の表示やハンドリングに際してFirebase Cloud Messaging(FCM)のSDKの組み込みが必要になります。

具体的な内容については公式ドキュメントをご確認ください。
https://firebase.google.com/docs/cloud-messaging/flutter/receive?hl=ja

🚧

iOSで画像などを添付したプッシュ通知に対応する場合)

画像や動画などを添付したリッチプッシュ通知に対応するにはExtensionの作成が必要です。
詳しくは リッチプッシュ通知に対応する をご覧ください。

前提条件

事前に karte_core パッケージの導入を行う必要があります。

KARTE ではプッシュ通知の送信に、Firebase Cloud Messaging(以下FCM)を利用しています。
そのためFCM経由でプッシュ通知を送信するための各種設定を行う必要があります。

また受信側のアプリケーションでもFirebaseライブラリの導入などの対応が必要となります。

なお本ドキュメントでは、firebase_messaging パッケージ を利用する前提で説明します。
これ以外のライブラリを利用する場合は、読み替えた上で導入を行ってください。

導入手順

STEP1: firebase_messaging を導入する

  1. SDKを導入する
    導入に関しては、下記ドキュメントをご覧ください。
  1. Notification Composer で通知のテストを行う
    Firebase の Notification Composer から通知メッセージを送信し、メッセージが受信できるか確認してください。
    Send a notification message

STEP2: サービスアカウントの設定を行う

KARTEからFCMに対して通知の送信リクエストを行うために、KARTE側にサービスアカウントの設定を行う必要があります。
サービスアカウントを設定する

STEP3: karte_notification を導入する

共通

アプリケーションの pubspec.yaml の dependencies にkarte_notificationパッケージを記入し、 pub get コマンドでインストールしてください。

dependencies:
  karte_notification: any
flutter pub get

STEP4: FCMトークンを送信する処理の実装

KARTE からプッシュ通知を送信するためには、FCMトークンが必要となります。
そのためアプリケーションからKARTEにFCMトークンを送信する処理を実装します。

KARTEにFCMトークンを送信する処理の実行は、こちらのタイミングでplugin_native_app_identifyイベントが適切に発火するかをご確認ください。

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:karte_notification/karte_notification.dart' as krt;

class _MyAppState extends State<MyApp> {
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;

  @override
  void initState() {
    super.initState();
    _firebaseMessaging.getToken().then((String? token) {
      if (token == null) return;
      // 取得したトークンをKARTEに送信
      krt.Notification.registerFCMToken(token);
    });
    _firebaseMessaging.onTokenRefresh.listen((String token) {
      // 更新されたトークンをKARTEに送信
      krt.Notification.registerFCMToken(token);
    });

    // ...
  }
}

STEP5: プラットフォーム毎の実装

KARTEのプッシュ通知はFCMを利用しているため、アプリでプッシュ通知の受信やタップ時の処理を行うには、firebase-messagingライブラリなどを用いたFlutterアプリの一般的な実装が必要です。

こちらの実装については、Firebase公式ドキュメントなどをご参照ください。

加えて、KARTEのSDKではプラットフォームのそれぞれに固有のメソッドがあり、以下のケースで、OS毎にfirebase-messagingのメソッドと合わせて実装が必要です。

🚧

Firebase Cloud Messaging SDKの組み込みについて

下記の KARTE SDKメソッドの実装要否 は、 KARTE SDKに関連する実装の要否 を意味します。
ネイティブアプリとしてのFirebase Cloud Messaging(FCM)を利用した通知を利用する場合、タップのハンドリング等で前提としてFCM SDKの組み込みが必須になる内容もあります。

具体的な組み込みの内容については公式ドキュメントをご確認ください。
https://firebase.google.com/docs/cloud-messaging/flutter/receive?hl=ja

OS処理内容KARTE SDKメソッドの実装要否Firebase Cloud Messaging SDKの組み込み
iOS通知の作成・表示不要
公式ドキュメントuni_linksapp_links などに従った組み込みが必要です
iOS通知タップ時のディープリンク遷移
公式ドキュメントuni_linksapp_links などに従った組み込みが必要です
Android通知の作成・表示
公式ドキュメントuni_linksapp_links などに従った組み込みが必要です
Android通知タップ時のディープリンク遷移不要
公式ドキュメントuni_linksapp_links などに従った組み込みが必要です

OS毎のSTEP5実装例

iOS: 通知タップ時のディープリンク遷移

通知タップ時にディープリンク遷移する場合は、firebase_messagingのメソッドで通知タップを検知し、そのコールバックでKARTE SDKのhandleForIOSメソッドを使用してください。

handleForIOSメソッドは、通知メッセージに含まれるディープリンクをハンドリングします。

※ディープリンクの処理には、Flutterアプリでディープリンクを処理するための外部ライブラリ(uni_linksapp_linksなど)の実装も合わせて必要です。

下記が実装例です。

import 'package:uni_links/uni_links.dart';

class _MyAppState extends State<MyApp> {

late StreamSubscription _linkSubscription;

@override
  void initState() {
    super.initState();

    // アプリ未起動状態から通知が開かれた際の処理
    RemoteMessage? message =
        await FirebaseMessaging.instance.getInitialMessage();
    if (message != null) {
        var karteNotification = await krt.Notification.create(message);
        if (karteNotification != null) {
          karteNotification.handleForIOS();
        }
    }

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
      // アプリ起動状態から通知が開かれた際の処理
      var karteNotification = await krt.Notification.create(message);
      if (karteNotification != null) {
        karteNotification.handleForIOS();
      }
    });

    // uni_links の実装
    // handle initial link
    try {
      final link = await getInitialLink();
      if (link != null) {
        // ディープリンクを処理します
      }
    } on PlatformException catch (e) {
      ...省略
    }

    // handle incoming links
    _linkSubscription = linkStream.listen((String? link) {
      if (link != null) {
        // ディープリンクを処理します
      }
    }, onError: (err) {
      ...省略
    });
  }
  ...
}

Android: 通知の作成・表示

通知を作成・表示する場合は、firebase_messagingのメソッドで通知を受信し、そのコールバックでKARTEのhandleForAndroidメソッドを使用してください。

handleForAndroidメソッドは、KARTE経由で送信された通知メッセージから、通知を作成・表示します。

※KARTEから送信されるメッセージはデータメッセージとして送信されます。データメッセージのため、アプリの状態(foreground / background)によって実装する処理が異なります。

下記が実装例です。

またタップ時のリンク遷移等をハンドリングしたい場合は、Firebaseのインタラクションの処理等に基づいた実装が必要です。

foreground時に受信する場合の実装

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:karte_notification/karte_notification.dart' as krt;

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      // アプリがforeground時に受信する場合
      var karteNotification = await krt.Notification.create(message);
      if (karteNotification != null) {
        karteNotification.handleForAndroid();
      }
    });

    // ...
  }
}

background時に受信する場合の実装

flutter v1.12未満を使用する場合 Flutter v1.12未満(Flutter Android Embedding V1)の場合、backgroundで受信した際に `karte_notification` モジュールで処理を行うためには、 `firebase_messaging` パッケージが起動するbackgroundの `FlutterNativeView` に `karte_notification` を登録する必要があります。 `FlutterApplication` を実装したクラスに、`firebase_messaging` のServiceを登録するコードを追記したところに `karte_notification` を登録するコードも追加します。
class YourApplication : FlutterApplication(), PluginRegistry.PluginRegistrantCallback {

    private val appKey = "YOUR_APP_KEY"
    override fun onCreate() {
        super.onCreate()

        FlutterFirebaseMessagingService.setPluginRegistrant(this)
        KarteApp.setup(this, appKey)
    }

    override fun registerWith(registry: PluginRegistry?) {
        if (registry?.hasPlugin("io.flutter.plugins.firebasemessaging") == false) {
            FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging"))
        }
        // KarteNotificationPluginをFirebaseMessagingServiceに登録する処理
        if (registry?.hasPlugin("io.karte.flutter.notifications") == false) {
            KarteNotificationPlugin.registerWith(registry.registrarFor("io.karte.flutter.notifications"))
        }
    }
}
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:karte_notification/karte_notification.dart' as krt;


Future<dynamic> myBackgroundMessageHandler(RemoteMessage message) async {
  // アプリがbackground時に受信した場合
  var karteNotification = await krt.Notification.create(message);
  if (karteNotification != null) {
    karteNotification.handleForAndroid();
  }
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
    FirebaseMessaging.onBackgroundMessage(myBackgroundMessageHandler);
    // ...
  }
}

動作確認

最後に正しく導入が行われているか確認を行うためにテストメッセージを送信して確認を行います。

詳細については、下記ドキュメントをご覧ください。

テストメッセージを送信する

[KARTE for AppのSDKインストール時に確認すべき内容](https://developers.karte.io/docs/sdk-implementation-checklist#プッシュ通知