1. はじめに
最終更新日: 2022 年 4 月 4 日
この Codelab では、Flutter を使用して Firebase Cloud Messaging(FCM)を備えたマルチプラットフォーム アプリを開発するプロセスについて説明します。アプリの実装の一部を記述し、Android、iOS、ウェブの 3 つのプラットフォームでシームレスにビルドして実行します。また、Flutter に FCM を統合する方法と、メッセージを受信して送信するコードを作成する方法についても学びます。最後に、この 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 デバイスを選択します。ターゲット選択ツールが空の場合は、仮想 Android デバイスをインストールします。ウェブブラウザまたは iOS デバイスからアプリを起動する場合は、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 はプロジェクト名とは異なる場合があります。プロジェクト 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.
矢印キーと Space キーを使用してプラットフォームを選択するか、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 services (APNs)] をオンにします。
- 鍵ファイル(ファイル拡張子
.p8
)をダウンロードします。 - Firebase コンソールで、プロジェクトの [プロジェクトの設定] に移動し、[Cloud Messaging] タブを選択します。
- [Cloud Messaging] タブで、iOS アプリの APNs キーファイルをアップロードします。[Cloud Messaging] タブで APN の鍵 ID とチーム ID を入力します。チーム ID は Apple メンバー センターで確認できます。
4. FCM の準備
アプリが FCM からメッセージを受信するには、次の要件を満たす必要があります。
- FlutterFire を初期化します。
- 通知権限をリクエストする。
- FCM に登録して登録トークンを取得します。
初期化
サービスを初期化するには、メイン関数(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
メソッドは、権限を許可または拒否するようユーザーに求めるダイアログまたはポップアップを表示します。
まず、このコードをメイン関数のコメント 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 でウェブアプリを再度実行すると、権限を求めるメッセージが再度表示される場合があります。
登録
このコードをコメント TODO: Register with FCM
の下のメイン関数にコピーして、FCM に登録します。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 として使用できるようにします。
次に、[登録] セクションの登録コードをこのコードに置き換えて、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
ファイルを作成します。ウェブアプリが onMessage
イベントを受信できるようにするには、次のコードを firebase-messaging-sw.js
にコピーします。詳細については、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
イベントを処理する必要があります。
フォアグラウンド メッセージ ハンドラ
まず、イベント ハンドラから UI にメッセージを渡すために、ファイル main.dart
のコメント TODO: Add stream controller
の後にストリーム コントローラを追加します。
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 以降では、ウェブベースのプラットフォームでバックグラウンド メッセージを処理するには、別のフローが必要です。そのため、サービス ワーカー 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!!");
}
- [登録] セクションからコピーした Android 登録トークンを、変数
registrationToken
の値に貼り付けます。 - [実行 ]
をクリックしてメイン関数を実行し、FCM を介してユーザーにメッセージを送信します。
Android アプリがバックグラウンドで動作している場合、メッセージは通知トレイに表示されます。
Android アプリがフォアグラウンドにある場合、Android Studio コンソールに「フォアグラウンド メッセージを処理しています」というログが表示されます。UI は新しいメッセージのストリーミング コントローラにサブスクライブされているため、メッセージの内容も UI に表示されます。
登録トークンを貼り付けて、アプリサーバーまたは他の信頼できるサーバー環境からメッセージを送信すると、同様の動作になります。
- ウェブアプリがバックグラウンドにある場合(別のウィンドウに隠れている場合や、別のタブがアクティブになっている場合など)は、ウェブ通知が表示されます。
- ウェブアプリがフォアグラウンドにある場合は、ウェブを右クリックして
Inspect
を選択すると、Chrome コンソールでログを表示できます。メッセージの内容も UI に表示されます。
6. トピック メッセージを送信する
FCM HTTP v1 API のプラットフォーム オーバーライド機能を使用すると、メッセージ送信リクエストの動作をプラットフォームごとに変えることができます。この機能のユースケースの 1 つは、プラットフォームに応じて異なる通知メッセージの内容を表示することです。この機能は、トピック メッセージングで複数のデバイス(複数のプラットフォームにまたがる可能性がある)をターゲットに設定する場合に最も効果的です。このセクションでは、アプリがプラットフォームごとにカスタマイズされたトピック メッセージを受信する手順について説明します。
クライアントからトピックに登録する
トピックにサブスクライブするには、Flutter アプリの main.dart
ファイルのメイン関数の末尾で 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());
}
アプリサーバーを起動し、[実行 ] をクリックして、
FcmSubscriptionManager.java
ファイルのメイン関数を実行します。
プラットフォームのオーバーライドを含むメッセージをトピックに送信する
これで、トピック プラットフォームのオーバーライド メッセージを送信する準備が整いました。次のコード スニペットでは、
- ベース メッセージとタイトル「
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
ファイルのメイン関数で、sendMessageToFcmTopic();
のコメント化を解除します。[実行 ] をクリックしてトピック メッセージを送信します。
7. まとめと次のステップ
ここまで、Flutter と FCM を使用して魅力的なマルチプラットフォーム アプリを開発する方法について学習しました。環境の設定、依存関係の統合、メッセージの受信と送信について説明しました。詳しくは、次の資料をご覧ください。
Codelab
- ユーザー認証やデータの同期など、Flutter が他の Firebase プロダクトと連携する仕組みについて詳しくは、Firebase for Flutter を理解するをご覧ください。
- アプリ内メッセージやトピックなど、FCM の詳細については、FCM と FIAM を使用してユーザーにメッセージを送信すると FCM トピックを使用した最初のマルチキャスト プッシュ メッセージをご覧ください。