Firebase Cloud Messaging を使ってみる


このクイックスタートでは、メッセージを確実に送信できるように、モバイル クライアント アプリとウェブ クライアント アプリで Firebase Cloud Messaging を設定する方法について説明します。サーバー環境については、サーバー環境と FCM をご覧ください。

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

ターゲット プラットフォームによっては、追加の必須設定手順が必要になります。

iOS+

メソッドの実装入れ替え

Apple デバイスで FCM Flutter プラグインを使用するには、メソッドの実装入れ替えが必要です。これがないと、FCM トークン処理などの主要な Firebase の機能が正常に動作しません。

Android

Google Play 開発者サービス

FCM クライアントには Android 4.4 以降を搭載しているデバイスが必要です。またそのデバイスには、Google Play 開発者サービスがインストールされているか、Google API を使用して Android 4.4 が動作しているエミュレータが搭載されている必要があります。ただし、開発した Android アプリは Google Play ストア経由以外の手段でもデプロイできます。

Play 開発者サービスの SDK に依存するアプリについては、Google Play 開発者サービス機能にアクセスする前に、互換性のある Google Play 開発者サービスの APK がデバイスにインストールされているかどうかをアプリが必ずチェックする必要があります。このチェックは、メイン アクティビティの onCreate() メソッドと onResume() メソッドの 2 か所で行うことをおすすめします。onCreate() では、チェックにパスしないとアプリを使用できないようにします。onResume() では、ユーザーが [戻る] ボタンなどの他の手段を使って実行中のアプリに戻った場合にもチェックされるようにします。

対応しているバージョンの Google Play 開発者サービスがデバイスにインストールされていない場合は、アプリで GoogleApiAvailability.makeGooglePlayServicesAvailable() を呼び出すと、ユーザーが Play ストアから Google Play 開発者サービスをダウンロードできるようになります。

ウェブ

FCM でウェブ認証情報を構成する

FCM のウェブ インターフェースでは、「Voluntary Application Server Identification 鍵(VAPID 鍵)」と呼ばれるウェブ認証情報を利用して、サポートされているウェブプッシュ サービスへの送信リクエストが承認されます。アプリをプッシュ通知にサブスクライブするには、鍵ペアを Firebase プロジェクトに関連付ける必要があります。Firebase コンソールを使用して、新しい鍵ペアを生成するか、既存の鍵ペアをインポートすることができます。

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

  1. Flutter 用の Firebase プラグインをインストールして初期化します(まだ行っていない場合)。

  2. Flutter プロジェクトのルートから、次のコマンドを実行してプラグインをインストールします。

    flutter pub add firebase_messaging
    
  3. 完了したら、Flutter アプリを再ビルドします。

    flutter run
    

登録トークンにアクセスする

特定のデバイスにメッセージを送信するには、デバイス登録トークンを知っておく必要があります。アプリ インスタンスの登録トークンを取得するには、getToken() を呼び出します。このメソッドに通知権限が付与されていない場合は、ユーザーに通知権限を付与するよう求められます。すでに通知権限が付与されている場合、このメソッドはトークンを返すか、エラーが発生するので future を拒否します。

// You may set the permission requests to "provisional" which allows the user to choose what type
// of notifications they would like to receive once the user receives a notification.
final notificationSettings = await FirebaseMessaging.instance.requestPermission(provisional: true);

// For apple platforms, make sure the APNS token is available before making any FCM plugin API calls
final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
if (apnsToken != null) {
 // APNS token is available, make FCM plugin API requests...
}

ウェブ プラットフォームで、VAPID 公開鍵を getToken() に渡します。

final fcmToken = await FirebaseMessaging.instance.getToken(vapidKey: "BKagOny0KF_2pCJQ3m....moL0ewzQ8rZu");

トークンが更新されるたびに通知を受けるには、onTokenRefresh ストリームに登録します。

FirebaseMessaging.instance.onTokenRefresh
    .listen((fcmToken) {
      // TODO: If necessary send token to application server.

      // Note: This callback is fired at each app startup and whenever a new
      // token is generated.
    })
    .onError((err) {
      // Error getting token.
    });

自動初期化を禁止する

FCM 登録トークンが生成されると、ライブラリによりその ID と構成データが Firebase にアップロードされます。トークンの自動生成を禁止する場合は、ビルド時に自動初期化を無効にします。

iOS

iOS では、メタデータ値を Info.plist に追加します。

FirebaseMessagingAutoInitEnabled = NO

Android

Android では、次のメタデータ値を AndroidManifest.xml に追加して、アナリティクスの収集と FCM 自動初期化を無効にします(両方を無効にする必要があります)。

<meta-data
    android:name="firebase_messaging_auto_init_enabled"
    android:value="false" />
<meta-data
    android:name="firebase_analytics_collection_enabled"
    android:value="false" />

FCM の自動初期化をランタイム時に再度有効にする

特定のアプリ インスタンスに対して自動初期化を有効にするには、setAutoInitEnabled() を呼び出します。

await FirebaseMessaging.instance.setAutoInitEnabled(true);

この値をいったん設定すると、アプリを再起動しても維持されます。

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

  1. 対象デバイスでアプリをインストールして実行します。Apple デバイスの場合、リモート通知受信権限に対するリクエストを承認する必要があります。
  2. アプリがデバイスのバックグラウンドで動作していることを確認します。
  3. Firebase コンソールで [Messaging] ページを開きます。
  4. メッセージを初めて作成する場合は、[最初のキャンペーンを作成] を選択します。
    1. [Firebase Notification メッセージ] を選択し、[作成] を選択します。
  5. それ以外の場合は、[キャンペーン] タブで [新しいキャンペーンを作成]、[通知] の順に選択します。
  6. 通知テキストを入力します。
  7. 右側のペインで [テスト メッセージを送信] を選択します。
  8. [FCM 登録トークンを追加] というラベルの付いたフィールドで、登録トークンを入力します。
  9. [テスト] を選択します。

[テスト] を選択すると、アプリをバックグラウンドで実行しているターゲット クライアント デバイスに通知が届きます。

アプリへのメッセージ配信については、FCM レポート ダッシュボードをご覧ください。このダッシュボードには、Android アプリのインプレッション データとともに、Apple と Android のデバイスで送信および開封されたメッセージの数が記録されています。

インタラクションの処理

ユーザーが通知をタップすると、Android と iOS のいずれも、デフォルトの動作ではアプリが開きます。アプリが終了している場合は、アプリが起動します。アプリがバックグラウンドで動作している場合は、フォアグラウンドに移動します。

通知の内容によっては、アプリを開くときにユーザーの操作を処理する必要が生じることがあります。たとえば、通知を使用して新しいチャット メッセージを送信した後にユーザーが通知を選択した場合、アプリの起動時に特定のスレッドを開きたいことがあります。

firebase-messaging パッケージには、このインタラクションを処理する 2 つの方法が用意されています。

  1. getInitialMessage():: アプリが終了状態から開いた状態になると、このメソッドは RemoteMessage を含む Future を返します。使用済みの RemoteMessage は削除されます。
  2. onMessageOpenedApp: アプリがバックグラウンド状態から開いた状態になった場合に、RemoteMessage を送信する Stream です。

ユーザーがスムーズに利用できるように、両方のシナリオに対処する必要があります。以下のサンプルコードは、この方法を示しています。

class Application extends StatefulWidget {
  @override
  State createState() => _Application();
}

class _Application extends State {
  // In this example, suppose that all messages contain a data field with the key 'type'.
  Future setupInteractedMessage() async {
    // Get any messages which caused the application to open from
    // a terminated state.
    RemoteMessage? initialMessage =
        await FirebaseMessaging.instance.getInitialMessage();

    // If the message also contains a data property with a "type" of "chat",
    // navigate to a chat screen
    if (initialMessage != null) {
      _handleMessage(initialMessage);
    }

    // Also handle any interaction when the app is in the background using a
    // Stream listener
    FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
  }

  void _handleMessage(RemoteMessage message) {
    if (message.data['type'] == 'chat') {
      Navigator.pushNamed(context, '/chat',
        arguments: ChatArguments(message),
      );
    }
  }

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

    // Run code required to handle interacted messages in an async function
    // as initState() must not be async
    setupInteractedMessage();
  }

  @override
  Widget build(BuildContext context) {
    return Text("...");
  }
}

インタラクションの処理方法は、設定によって異なります。前述の例は、StatefulWidget の基本的な使用例です。

次のステップ

設定手順の完了後、Flutter 用 FCM で開発を進めるための方法をいくつか次に示します。