Firebase Cloud MessagingでFlutter Web Appにプッシュ通知を送信してみた

2022.04.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

Flutterアプリへのプッシュ通知の実装について検討していたところ、Firebase Cloud Messagingが便利だと聞きました。

今回は、Firebase Cloud Messaging(FCM)でFlutter Web Appにプッシュ通知を送信してみました。

やってみた

下記ドキュメントを参考に、FCMのコンソールからテスト通知をFlutter Web Appへ送信できるようにしてみます。

Firebase CLIのインストール、認証

Firebase CLIをグローバルインストールします。

$ npm install -g firebase-tools

パスが通っていることを確認します。

$ firebase --version
10.6.0

Firebase CLIの認証を行います。次のコマンドを実行するとブラウザ画面が開き、Firebase(Google)の認証およびアクセス権の委譲を求められるのでサインインおよび許可します。

$ firebase login

CLI画面に戻り、次のように表示されれば認証成功です。

✔  Success! Logged in as hoge@example.com

参考

flutter project作成

Flutterプロジェクトを新規作成します。

$ flutter create flutter_sample_app
$ cd flutter_sample_app

https://pub.dev/packages/firebase_coreプラグインをインストールします。

$ flutter pub add firebase_core

この時作成されるlib/generated_plugin_registrant.dartでエラーが発生しているかと思いますが、後節で対応するので一旦無視してください。

Target of URI doesn't exist: 'package:firebase_core_web/firebase_core_web.dart'. Try creating the file referenced by the URI, or Try using a URI for a file that does exist.

FlutterFire CLIのインストール

FlutterFire CLIをグローバルインストールします。

$ dart pub global activate flutterfire_cli

FlutterFire CLIにパスを通します。

$ export PATH="$PATH":"$HOME/.pub-cache/bin"

FlutterFire CLIにパスが通っていることを確認します。

$ flutterfire --version
0.2.0

次のコマンドを実行してFirebaseにFlutter Web App用のプロジェクトを作成します。

$ flutterfire configure
✔ Enter a project id for your new Firebase project (e.g. my-cool-project) · flutter-wakatsuki-app
✔ Which platforms should your configuration support (use arrow keys & space to select)? · web

この時作成されるlib/firebase_options.dartでも先程と同様のエラーが発生しているかと思います。

次のコマンドを実行して不足しているパッケージをインストールします。するとエラーは解消するはずです。

$ flutter packages get

アプリへのCloud Messagingの導入

Firebase Cloud Messagingのコンソールで、先程作成したプロジェクトのWeb Push certificateを作成し、Key pairを控えます。

FCMのパッケージをインストールします。

$ flutter pub add firebase_messaging

main.dartの冒頭を次のように修正します。messaging.getToken()vapidKeyには先程取得したKey pairを指定します。これによりパーミッションの設定、トークンの取得およびフォワグラウンドでのメッセージのリッスンをできるようにします。

lib/main.dart

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

void main() async {
  //イニシャライズ
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  //パーミションの設定
  FirebaseMessaging messaging = FirebaseMessaging.instance;
  NotificationSettings settings = await messaging.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );
  print('User granted permission: ${settings.authorizationStatus}');

  //トークン取得
  String token = (await messaging.getToken(
    vapidKey: "BGpdLRs......",
  ))
      .toString();
  print(token);

  //メッセージのリッスン
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    print('Got a message whilst in the foreground!');

    if (message.notification != null) {
      print('onForegroundMessage Title: ${message.notification?.title}');
      print('onForegroundMessage Body: ${message.notification?.body}');
    }
  });

  runApp(const MyApp());
}

こちらを参考にweb/firebase-messaging-sw.jsを作成します。これによりFirebase Cloud Messagingのテストメッセージをバックグラウンドでもリッスンできるようにします。

web/firebase-messaging-sw.js

importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js");

firebase.initializeApp({
  apiKey: "AIzaSyAgUhHU8wSJgO5MVNy95tMT07NEjzMOfz0",
  authDomain: "react-native-firebase-testing.firebaseapp.com",
  databaseURL: "https://react-native-firebase-testing.firebaseio.com",
  projectId: "react-native-firebase-testing",
  storageBucket: "react-native-firebase-testing.appspot.com",
  messagingSenderId: "448618578101",
  appId: "1:448618578101:web:ecaffe2bc4511738",
});
// Necessary to receive background messages:
const messaging = firebase.messaging();

// Optional:
messaging.onBackgroundMessage((m) => {
  console.log("onBackgroundMessage", m);
});

またweb/index.html<body>の末尾に次のコードを追記します。これにより前述のjsファイルをサービスワーカーとして起動中のアプリに登録します。

web/index.html

  <script>
    if ("serviceWorker" in navigator) {
      window.addEventListener("load", function () {
        navigator.serviceWorker.register("/firebase-messaging-sw.js");
      });
    }
  </script>
</body>

動作確認

Flutter Web AppをChromeで起動します。

$ flutter run -d chrome

するとChromeブラウザでアプリが起動し、通知の許可を求められるので許可します。

またコンソールに表示されたトークンを控えます。

Firebase Cloud Messagingのコンソールで、[Cloud Messaging]で[Send your first message]をクリック。

[Notification title]および[Notification Text]を指定して、[Send test message]をクリック。

先程控えたトークンを指定して、[Test]をクリック。

するとFlutter Web Appにプッシュ通知が届きました!Chromeがフォアグラウンドである場合のメッセージとなっています。

またChromeをバックグラウンドとした状態で同じトークンを使用して再度テストメッセージを送信すると、次はバックグラウンドである場合のメッセージも届きました!

おわりに

Firebase Cloud Messaging(FCM)でFlutter Web Appにプッシュ通知を送信してみました。

Firebaseを扱うのはほぼ初めてでかなり試行錯誤をしましたが、なんとか動かせはしました。次回以降ではiOSなどのネイティブアプリで試してみたいです。

参考

以上