1. はじめに
最終更新日: 2022 年 4 月 4 日
この Codelab では、Flutter を使用して Firebase Cloud Messaging(FCM)でマルチプラットフォーム アプリを開発するプロセスについて説明します。アプリの実装の一部を記述し、Android、iOS、ウェブの 3 つのプラットフォームでシームレスにビルドして実行します。また、FCM を Flutter に統合する方法と、メッセージを送受信するためのコードを記述する方法も学習します。最後に、この Codelab では、FCM HTTP v1 API のプラットフォーム固有のブロック機能を紹介します。これにより、プラットフォームごとに異なる動作の 1 つのメッセージを送信できます。
要件
Flutter に関する基礎知識。
ラボの内容
- Flutter アプリの設定方法と作成方法
- FCM の依存関係を追加する方法
- アプリに単一の FCM メッセージを送信する方法
- アプリにトピック FCM メッセージを送信する方法
必要なもの
- Dart プラグインと Flutter プラグインが構成された Android Studio の最新の安定版。
この Codelab は、次のいずれかのデバイスを使用して実行できます。
- パソコンに接続されている物理的な Android デバイス。
- Android Emulator(Android Emulator 上でアプリを実行するを参照)
- Chrome などの任意のブラウザ。
必要に応じて、iOS プラットフォームを使用して Codelab を実行するには、iOS デバイス、Apple デベロッパー アカウント、XCode がインストールされた macOS デバイスが必要です。
2. Flutter のセットアップ
Flutter の開発環境がすでにセットアップされている場合は、このセクションをスキップしてください。
Flutter の開発環境をセットアップする手順は次のとおりです。
- ご使用のオペレーティング システムに対応した Flutter をダウンロードしてインストールします。インストール | Flutter
- Flutter ツールがパスに追加されていることを確認します。
- エディタを設定する | Flutter の手順に沿って、Flutter 用のエディタを設定します。エディタに Flutter プラグインと Dart プラグインを必ずインストールしてください。この Codelab の残りの部分では、Android Studio を使用します。
- コマンドラインから
flutter doctor
を実行します。これにより、設定がスキャンされ、修正が必要な不足している依存関係が一覧表示されます。手順に沿って、重要な不足している依存関係を修正します。一部の依存関係は必要ない場合があります。たとえば、iOS 向けの開発を行う予定がない場合は、CocoaPods の依存関係がないことが問題になることはありません。 - 次のコマンドを実行して、
fcmflutter
ディレクトリflutter create --org com.flutter.fcm --project-name fcmflutter fcmflutter
に Flutter アプリを作成し、ディレクトリをfcmflutter
に変更します。
- Android Studio で [File] -> [Open] に移動し、Flutter アプリのパスを見つけて [Open] をクリックし、Android Studio でプロジェクトを開きます。アプリコードは
lib/main.dart
ファイルにあります。
Android Studio のツールバーで、下矢印をクリックして Android デバイスを選択します。ターゲット セレクタが空の場合は、ウェブブラウザまたは iOS デバイスからアプリを起動する場合は、仮想 Android デバイス、または Chrome ブラウザまたは iOS シミュレータをインストールします。対象のデバイスを見つけるには、デバイスを手動で起動し、リストを更新する必要があります。
実行 アイコン をクリックしてアプリを起動します。
これで完了です。これで、Flutter アプリの作成が完了しました。
3. Firebase と FlutterFire の設定
Flutter を使用して Firebase Cloud Messaging と統合するアプリを開発するには、以下が必要です。
- Firebase プロジェクト
- 機能する Firebase CLI。
- FlutterFire のインストール。
flutterfire configure
で設定および生成されたアプリ。
Firebase プロジェクトを作成する
Firebase プロジェクトがすでに存在する場合は、この手順をスキップできます。
- Google アカウントをお持ちの場合は、Firebase を開き、Google アカウントでログインして [コンソールへ移動] をクリックします。
- Firebase コンソールで [プロジェクトを追加] をクリックします。手順に沿ってプロジェクトを作成します。このプロジェクトでは Google アナリティクスは使用しないため、[このプロジェクトで Google アナリティクスを有効にする] はオンにしないでください。
- プロジェクトが作成されたら、[プロジェクトの概要] の横にある歯車アイコンをクリックして、プロジェクトの [プロジェクトの設定] に移動します。
[プロジェクト ID] はプロジェクトを一意に識別するために使用されます。[プロジェクト名] とは異なる場合があります。プロジェクト ID は、後で FlutterFire を設定するために使用します。
これで完了です。Firebase プロジェクトが正常に作成されました。
Firebase CLI を設定する
Firebase CLI を設定している場合は、この手順をスキップできます。
Firebase CLI リファレンスにアクセスして、Firebase CLI をダウンロードしてインストールします。次のコマンドを使用して、Google アカウントで Firebase にログインします。
firebase login
FlutterFire をセットアップする
- コマンド
flutter pub add firebase_core
を使用して FlutterFire プラグインをインストールします。 - FCM プラグインをインストールします。
flutter pub add firebase_messaging
- FlutterFire CLI を設定します。
dart pub global activate flutterfire_cli
- Flutter で Firebase プロジェクトを構成します。
flutterfire configure --project=fcm4flutter.
矢印キーとスペースを使用してプラットフォームを選択するか、Enter キーを押してデフォルトのプラットフォームを使用します。
この Codelab ではデフォルトのプラットフォーム(Android、iOS、ウェブ)を使用しますが、選択できるプラットフォームは 1 つまたは 2 つだけです。iOS バンドル ID の入力を求められたら、「com.flutter.fcm.fcmflutter
」または独自の iOS バンドル ID を「[company domain name].[project name]
」の形式で入力します。コマンドが完了したら、Firebase コンソールのページを更新します。Firebase プロジェクトに、選択したプラットフォーム用のアプリが作成されたことを確認できます。
このコマンドは、lib
ディレクトリに firebase_options.dart
ファイルを生成します。このファイルには、初期化に必要なすべてのオプションが含まれています。
iOS 用に Cloud Messaging を設定する
- Apple のデベロッパー ページに移動し、[キー] タブの [キーを作成] をクリックします。
- キーの名前を入力し、[Apple Push Notifications サービス(APNs)] チェックボックスをオンにします。
- キーファイルをダウンロードします(ファイル拡張子は
.p8
)。 - Firebase コンソールでプロジェクトの [プロジェクトの設定] に移動し、[Cloud Messaging] タブを選択します。
- [Cloud Messaging] タブで、iOS アプリの APNs キーファイルをアップロードします。[Cloud Messaging] タブの APNs キー ID とチーム ID(Apple メンバーシップ センターで確認)を入力します。
4. FCM の準備
アプリが FCM からメッセージを受信するには、以下のことを行う必要があります。
- FlutterFire を初期化します。
- 通知権限をリクエストする。
- FCM に登録して登録トークンを取得します。
初期化
サービスを初期化するには、main 関数(lib/main.dart
)を次のコードに置き換えます。
// core Flutter primitives
import 'package:flutter/foundation.dart';
// core FlutterFire dependency
import 'package:firebase_core/firebase_core.dart';
// generated by
flutterfire configure
import 'firebase_options.dart';
// FlutterFire's Firebase Cloud Messaging plugin
import 'package:firebase_messaging/firebase_messaging.dart';
// TODO: Add stream controller
// TODO: Define the background message handler
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// TODO: Request permission
// TODO: Register with FCM
// TODO: Set up foreground message handler
// TODO: Set up background message handler
runApp(MyApp());
}
次に、Android Studio で [Tools] -> [Flutter] -> [Flutter Pub Get] を実行して、FlutterFire のセットアップで追加したパッケージを読み込み、Android Studio に適切な Intellisense を設定してコードを表示します。
これにより、生成された firebase_options.dart
ファイルからインポートされた現在のプラットフォーム DefaultFirebaseOptions.currentPlatform
の FlutterFire が初期化されます。initializeApp
は非同期関数であり、await
キーワードにより、アプリを実行する前に初期化が完了することに注意してください。
権限をリクエストする
アプリは、通知を受信する許可をユーザーに求める必要があります。firebase_messaging
が提供する requestPermission
メソッドは、権限の許可または拒否をユーザーに求めるダイアログまたはポップアップを表示します。
まず、このコードを main 関数のコメント TODO: Request permission
にコピーします。返された settings
は、ユーザーが権限を付与したかどうかを示します。ユーザーがアクセスを必要とする機能を使用する必要がある場合(たとえば、ユーザーがアプリ設定で通知をオンにした場合)にのみ、権限をリクエストすることをおすすめします。この Codelab では、わかりやすくするためにアプリの起動時に権限をリクエストします。
final messaging = FirebaseMessaging.instance;
final settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (kDebugMode) {
print('Permission granted: ${settings.authorizationStatus}');
}
次に、Android Studio のツールバーで、ターゲット セレクタから Chrome (web)
を選択して、アプリを再度実行します。
Chrome のタブが開き、許可を求めるポップアップが表示されます。Allow
をクリックすると、Android Studio コンソールに Permission granted: AuthorizationStatus.authorized
というログが表示されます。権限リクエストを許可またはブロックすると、レスポンスがアプリとともにブラウザに保存され、ポップアップが再度表示されることはありません。Android Studio でウェブアプリを再度実行すると、権限を再度求められる場合があります。
登録
FCM に登録するには、このコードをコメント TODO: Register with FCM
の下の main 関数にコピーします。getToken
呼び出しは、アプリサーバーまたは信頼できるサーバー環境でユーザーにメッセージを送信するために使用できる登録トークンを返します。
// It requests a registration token for sending messages to users from your App server or other trusted server environment.
String? token = await messaging.getToken();
if (kDebugMode) {
print('Registration Token=$token');
}
Android Studio のツールバーで、Android デバイスを選択してアプリを実行します。Android Studio コンソールには、登録トークンが次のように表示されます。
I/flutter ( 3717): Permission granted: AuthorizationStatus.authorized I/flutter ( 3717): Registration Token=dch. . . D2P:APA9. . .kbb4
後でメッセージを送信するために使用するため、テキスト エディタにコピーします。
uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in library [:firebase_messaging]
ウェブ上でメッセージを受信するための追加手順
ウェブアプリで登録トークンを取得して受信メッセージをリッスンするには、追加の手順が 2 つ必要です。サポートされているウェブプッシュ サービスへの送信リクエストを承認するには、ウェブから getToken
に VAPID キーを渡す必要があります。
まず、Firebase コンソールで Firebase プロジェクトの [Cloud Messaging] タブを開き、[ウェブの構成] セクションまでスクロールして、既存の鍵ペアを見つけるか、新しい鍵ペアを生成します。ハイライト表示されたボタンをクリックしてキーをコピーし、vapidKey として使用できるようにします。
次に、[Registration] セクションの登録コードを次のコードに置き換えて、vapidKey を更新します。
// TODO: replace with your own VAPID key
const vapidKey = "<YOUR_PUBLIC_VAPID_KEY_HERE>";
// use the registration token to send messages to users from your trusted server environment
String? token;
if (DefaultFirebaseOptions.currentPlatform == DefaultFirebaseOptions.web) {
token = await messaging.getToken(
vapidKey: vapidKey,
);
} else {
token = await messaging.getToken();
}
if (kDebugMode) {
print('Registration Token=$token');
}
次に、プロジェクトのルートの web/
ディレクトリの下に firebase-messaging-sw.js
ファイルを作成します。以下を firebase-messaging-sw.js
にコピーして、ウェブアプリが onMessage
イベントを受信できるようにします。詳細については、Service Worker での通知オプションの設定をご覧ください。
importScripts("https://www.gstatic.com/firebasejs/9.6.10/firebase-app-compat.js");
importScripts("https://www.gstatic.com/firebasejs/9.6.10/firebase-messaging-compat.js");
// todo Copy/paste firebaseConfig from Firebase Console
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
// todo Set up background message handler
その後、[プロジェクト設定] -> [全般] タブで下にスクロールして [ウェブアプリ] を見つけ、firebaseConfig
コード セクションをコピーして firebase-messaging-sw.js
に貼り付けます。
最後に、Android Studio のツールバーで、ターゲット セレクタの Chrome (web)
を選択してアプリを実行します。Android Studio コンソールには、登録トークンが次のように表示されます。
Debug service listening on ws://127.0.0.1:61538/BLQQ3Fg-h7I=/ws Permission granted: AuthorizationStatus.authorized Registration Token=fH. . .ue:APA91. . .qwt3chpv
後でメッセージを送信する際に使用できるように、登録トークンをテキスト エディタにコピーします。
iOS でメッセージを受信するための追加手順
FCM からメッセージを受信するには、iOS デバイスで Xcode でプッシュ通知とバックグラウンド モードを有効にする必要があります。
- Android Studio でプロジェクト名を右クリックし、[Flutter] -> [Open iOS module in Xcode] を選択します。
- Xcode が起動したら、プロジェクト ターゲットの [Signing & Capabilities] タブで [Push Notifications] と [Background Modes] を有効にします。詳細については、アプリを設定するをご覧ください。
- Android Studio のツールバーで、ターゲット セレクタで iOS デバイスを選択してアプリを実行します。通知権限が付与されると、登録トークンが Android Studio コンソールに出力されます。
これで、FCM へのアプリの登録が完了しました。メッセージを受信する準備が整いました。次のセクションで説明します。
5. FCM からメッセージを受信する
メッセージ ハンドラを設定する
アプリは、フォアグラウンド モードのときにメッセージが届いた場合は onMessage
イベントを処理し、アプリがバックグラウンドで実行されている場合は onBackgroundMessage
イベントを処理する必要があります。
フォアグラウンド メッセージ ハンドラ
まず、main.dart
ファイルのコメント TODO: Add stream controller
の後にストリーム コントローラを追加して、イベント ハンドラから UI にメッセージを渡します。
import 'package:rxdart/rxdart.dart';
// used to pass messages from event handler to the UI
final _messageStreamController = BehaviorSubject<RemoteMessage>();
依存関係 rxdart を追加するには、プロジェクト ディレクトリから flutter pub add rxdart
コマンドを実行します。
次に、Android Studio で [Tools] -> [Flutter] -> [Flutter Pub Get] と順に実行し、rxdart.dart
パッケージを読み込み、Android Studio で適切な Intellisense 設定でコードを表示します。
次に、コメント TODO: Set up foreground message handler
の後に、フォアグラウンド メッセージをリッスンするイベント ハンドラを追加します。ログを出力し、メッセージをストリーム コントローラに公開します。
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
if (kDebugMode) {
print('Handling a foreground message: ${message.messageId}');
print('Message data: ${message.data}');
print('Message notification: ${message.notification?.title}');
print('Message notification: ${message.notification?.body}');
}
_messageStreamController.sink.add(message);
});
その後、main.dart
ファイルにある元の State ウィジェットを次のコードに置き換えます。これにより、State ウィジェットのストリーム コントローラにサブスクライバーが追加され、最後のメッセージがウィジェットに表示されます。
class _MyHomePageState extends State<MyHomePage> {
String _lastMessage = "";
_MyHomePageState() {
_messageStreamController.listen((message) {
setState(() {
if (message.notification != null) {
_lastMessage = 'Received a notification message:'
'\nTitle=${message.notification?.title},'
'\nBody=${message.notification?.body},'
'\nData=${message.data}';
} else {
_lastMessage = 'Received a data message: ${message.data}';
}
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Last message from Firebase Messaging:',
style: Theme.of(context).textTheme.titleLarge),
Text(_lastMessage, style: Theme.of(context).textTheme.bodyLarge),
],
),
),
);
}
}
Android/iOS のバックグラウンド メッセージ ハンドラ
メッセージは、アプリがバックグラウンドで動作している間、onBackgroundMessage
ハンドラによって処理されます。ハンドラはトップレベル関数である必要があります。アプリがフォアグラウンドになったら、メッセージの処理(インタラクションの処理を参照)やアプリサーバーとの同期によって、UI を更新できます。
ハンドラ関数を main 関数の外部でコメント TODO: Define the background message handler
の後に作成し、main 関数でコメント TODO: Set up background message handler
の後に呼び出します。
// TODO: Define the background message handler
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
if (kDebugMode) {
print("Handling a background message: ${message.messageId}");
print('Message data: ${message.data}');
print('Message notification: ${message.notification?.title}');
print('Message notification: ${message.notification?.body}');
}
}
void main() {
...
// TODO: Set up background message handler
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyApp());
}
ウェブ用のバックグラウンド メッセージ ハンドラ
FlutterFire の firebase_messaging バージョン 11.2.8 では、ウェブベースのプラットフォームでバックグラウンド メッセージを処理する場合に異なるフローが必要になります。そのため、Service Worker web/firebase-messaging-sw.js
に別のメッセージ ハンドラを追加する必要があります。
messaging.onBackgroundMessage((message) => {
console.log("onBackgroundMessage", message);
});
アプリサーバーを設定する
- Android Studio で https://github.com/FirebaseExtended/firebase_fcm_flutter/tree/main/server プロジェクトを開いて、スターター サーバーコードをインポートします。サーバーは Gradle ベースの Java プロジェクトであり、FCM メッセージ送信機能を提供する firebase-admin SDK に依存しています。
- Firebase Admin SDK が FCM API の呼び出しを承認できるように、Firebase サービス アカウントを設定します。Firebase コンソールで [プロジェクトの設定] を開き、[サービス アカウント] タブを選択します。[Java] を選択し、[
Generate new private key
] をクリックして構成スニペットをダウンロードします。 - ファイル名を
service-account.json
に変更し、サーバー プロジェクトのsrc/main/resources
パスにコピーします。
テスト メッセージを送信する
FcmSender.java
ファイルで、sendMessageToFcmRegistrationToken
はデータ ペイロードを含む通知メッセージを作成します。登録トークンはメッセージの送信先であるアプリ インスタンスをターゲットにします。
private static void sendMessageToFcmRegistrationToken() throws Exception {
String registrationToken = "REPLACE_WITH_FCM_REGISTRATION_TOKEN";
Message message =
Message.builder()
.putData("FCM", "https://firebase.google.com/docs/cloud-messaging")
.putData("flutter", "https://flutter.dev/")
.setNotification(
Notification.builder()
.setTitle("Try this new app")
.setBody("Learn how FCM works with Flutter")
.build())
.setToken(registrationToken)
.build();
FirebaseMessaging.getInstance().send(message);
System.out.println("Message to FCM Registration Token sent successfully!!");
}
- [Registration] セクションからコピーした Android 登録トークンをコピーし、変数
registrationToken
の値に貼り付けます。 - 実行 アイコン をクリックして main 関数を実行し、FCM 経由でユーザーにメッセージを送信します。
Android アプリがバックグラウンドで動作しているときは、通知トレイにメッセージが表示されます。
Android アプリがフォアグラウンドにあるときは、Android Studio コンソールに「Handling a forfground message」というログが表示されます。UI は新しいメッセージのストリーム コントローラに登録されるため、メッセージの内容は UI にも表示されます。
登録トークンを貼り付けて、アプリサーバーまたは他の信頼できるサーバー環境からメッセージを送信する場合も、同様の動作になります。
- ウェブアプリがバックグラウンドで実行されている場合(つまり、別のウィンドウで非表示になっている場合や、別のタブがアクティブになっている場合)は、ウェブ通知が表示されます。
- ウェブアプリがフォアグラウンドにある場合、ウェブを右クリックして
Inspect
を選択すると、Chrome コンソールでログを表示できます。メッセージの内容は UI にも表示されます。
6. トピック メッセージを送信する
FCM HTTP v1 API のプラットフォーム オーバーライド機能を使用すると、メッセージ送信リクエストの動作をプラットフォームごとに変えることができます。この機能の 1 つのユースケースは、プラットフォームに応じて異なる通知メッセージ コンテンツを表示することです。この機能は、トピック メッセージングで複数のデバイス(複数のプラットフォームにまたがる可能性がある)をターゲットとする場合に最大限に活用されます。このセクションでは、プラットフォームごとにカスタマイズされたトピック メッセージをアプリで受信するための手順を説明します。
クライアントからトピックにサブスクライブする
トピックにサブスクライブするには、Flutter アプリの main.dart
ファイルにある main 関数の最後に messaging.subscribeToTopic
メソッドを呼び出します。
// subscribe to a topic.
const topic = 'app_promotion';
await messaging.subscribeToTopic(topic);
[省略可] ウェブ用サーバーからトピックにサブスクライブする
ウェブ プラットフォームで開発していない場合は、このセクションをスキップできます。
FCM JS SDK は現在、クライアント側のトピック サブスクリプションをサポートしていません。代わりに、Admin SDK のサーバーサイド トピック管理 API を使用してサブスクライブできます。次のコードは、Java Admin SDK を使用したサーバーサイドのトピック サブスクリプションを示しています。
private static void subscribeFcmRegistrationTokensToTopic() throws Exception {
List<String> registrationTokens =
Arrays.asList(
"REPLACE_WITH_FCM_REGISTRATION_TOKEN"); // TODO: add FCM Registration Tokens to
// subscribe
String topicName = "app_promotion";
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(registrationTokens, topicName);
System.out.printf("Num tokens successfully subscribed %d", response.getSuccessCount());
}
アプリサーバーを開き、[Run ] をクリックして、FcmSubscriptionManager.java
ファイルの main 関数を実行します。
プラットフォームのオーバーライドを含むメッセージをトピックに送信する
これで、トピック プラットフォーム オーバーライド メッセージを送信する準備が整いました。次のコード スニペットで、次のようになります。
- ベース メッセージとタイトル「
A new app is available
」の送信リクエストを作成します。 - このメッセージは、iOS およびウェブ プラットフォームで「
A new app is available
」というタイトルの表示通知を生成します。 - このメッセージは、Android デバイスで「
A new Android app is available
」というタイトルの表示通知を生成します。
private static void sendMessageToFcmTopic() throws Exception {
String topicName = "app_promotion";
Message message =
Message.builder()
.setNotification(
Notification.builder()
.setTitle("A new app is available")
.setBody("Check out our latest app in the app store.")
.build())
.setAndroidConfig(
AndroidConfig.builder()
.setNotification(
AndroidNotification.builder()
.setTitle("A new Android app is available")
.setBody("Our latest app is available on Google Play store")
.build())
.build())
.setTopic("app_promotion")
.build();
FirebaseMessaging.getInstance().send(message);
System.out.println("Message to topic sent successfully!!");
}
FcmSender.java
ファイルの main 関数で、sendMessageToFcmTopic();
のコメント化を解除します。実行 アイコン をクリックして、トピック メッセージを送信します。
7. まとめと次のステップ
ここまでのまとめとして、Flutter と FCM を使用したマルチプラットフォーム アプリ開発について学習しました。これには、環境のセットアップ、依存関係の統合、メッセージの送受信が含まれます。詳細については、次の資料をご覧ください。
Codelab
- ユーザー認証やデータの同期など、他の Firebase プロダクトと Flutter が連動する仕組みについては、Firebase for Flutter についてをご覧ください。
- アプリ内メッセージングやトピックなど、FCM について詳しくは、FCM と FIAM を使用してユーザーにメッセージを送信すると FCM トピックを使用した最初のマルチキャスト push メッセージをご覧ください。