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

2022.04.17

こんにちは、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);

  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をローカルで起動します。

$ 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にプッシュ通知が届きました!

注意点

ちなみに同じトークンを使用して再度テスト通知を送ることはできないようです。同じトークンを再度使うとこのように表示され上手くメッセージを受信できません。

再度送りたい場合は新しく作成したトークンを使用します。今回の環境であればアプリを一度終了して再度起動し(Hot Reloadではない)、新しく取得したトークンでテスト通知を行います。

おわりに

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

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

参考

以上