Flutter #2 Advent Calendar 2020 の 16日目 の記事となります。
Flutterが気になる方は Flutter #1 やFlutter #3もありますので、ぜひご覧になってください。
概要
私が初めてPush通知を実装したとき苦労した記憶がありました。そこで初めてのモバイルアプリ開発をFlutterで行う人に対しての「この記事を参考にすれば最低限のPush通知が確認できる」という内容にしました。
また、基本的には下記pluginページの流れと同じものになります。
https://pub.dev/packages/firebase_messaging
※ このFCM用の設定を本番、開発で切り替えたい場合はこちらの記事を参考にしてください。
前提
- Flutterの環境構築は完了している
- Firebaseを使ってPush通知を実装したい
環境
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.4, on Mac OS X 10.15.7 19H2 darwin-x64, locale en-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 12.1)
[✓] Android Studio (version 4.1)
[✓] Connected device (1 available)
サンプルコード
Flutterプロジェクトの作成
Create New Flutter Projectを選択します。

次にどのタイプのプロジェクトを作成するか聞かれるのでFlutter Applicationを選択します。
Project nameはflutter_fcm_first_sampleとしました。
Package nameはcom.yana1316.flutter_fcm_first_sampleとしました。この名前はFirebaseやXcodeの設定でも使いますので覚えておいて下さい。
Firebaseでプロジェクトの作成
Firebaseのアカウントの作成
Googleアカウントが無い方は作成してください。
プロジェクトの追加
プロジェクト名をflutter-fcm-first-sampleとしました。Google Analyticsの追加は、どちらでも大丈夫です。
Android用設定
Firebase設定
アプリの登録
プロジェクト追加後、画面上からAndroid用アプリを登録します。

Android パッケージ名
Android StudioでProject作成時に設定したPackage nameを入力します。
パッケージ名を忘れてしまった場合
Android Studioで確認できます。 設定ファイルのダウンロード
google-services.jsonをダウンロードし、[project]/android/app/に置きます。

google-services.jsonは機密情報ではありませんが、公開されたgit等で管理しないようにしましょう。(いろいろと狙われる原因になりがちですので)
Firebase SDK の追加(スキップ)
何もせず次へを押してスキップします。
次のステップ
何もせずコンソールに進むを押します。
Android Studioでの設定
[project]/android/build.gradleに追記します。
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.4' // 追記
}
`com.google.gms:google-services` の最新バージョン
以下のページの`Google Play services plugin`で最新バージョンを確認することができます。 https://firebase.google.com/support/release-notes/android#latest_sdk_versions[project]/android/app/build.gradleに追記します。
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services' // 追記
[project]/android/app/src/main/AndroidManifest.xmlの40行目付近に追記します。
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
※ 今回、バックグラウンド処理用の設定は省略しています。詳細は以下から確認してください。
https://pub.dev/packages/firebase_messaging#optionally-handle-background-messages
iOS用設定
Apple Developer Programでの設定
アカウントの作成
Apple IDでも開発できるのですが、たぶんPush通知を行うには有料のApple Deeloper Programに登録する必要がありそうです。下記ページのAppの高度な機能とサービスにPush通知で利用するPush Notifications機能が含まれている気がします。
https://developer.apple.com/jp/support/compare-memberships/
Apple Developer Programのアカウントを作成したらログインして、以下のCertificates, Identifiers & Profilesに移動します。

Keys の作成
Certificates, Identifiers & Profilesに移動後、左メニューのKeysをクリックします。
+ボタンを押して新しいKeyを追加します。Keyの名前はご自由にですがproduct keyとかmain keyとかにするのでしょうか。
※ このKeyは、1つのアカウントで2つまでしか作れません。つまり複数のアプリを作ったとしても共通のKeyとなります。
※ 今回はFirebase FCMを使ってのPush通知となりますので、APNs用証明書(.cer)(.p12)は使わず、FirebaseがおすすめするAPNs認証キー(.p8)を使います。
Xcodeの設定
Android StudioのProject Windowから下記の[project]/iosを右クリックしFlutter内のOpen iOS module in Xcodeをクリックします。すると該当ProjectのXcodeが開きます。

アカウント設定
Xcode画面左上のほうにあるShow the project navigatorをクリックしRunnnerをクリックします。

Automatically manage signingにチェックを付け、Teamで自分のApple Deeloper Program アカウントを選択(追加)します。
`Automatically manage signing`での設定について
※ Signingにはいくつかの方法がありますが、Autoでの説明をしています。この他に`Apple Developer Program`に自分で証明書を用意する方法、`fastlane`などを使ってチーム内で証明書を簡単に共有しつつ設定する方法などがあります。 ※ `Automatically manage signing`にチェックをつけるとXcodeが`Apple Developer Program`にログインし、証明書をアップロードしてくれます。`Identifiers`のページを見ると `XC`から始まる証明書が登録されていますが、これは`Xcode`が登録したもので、`XC`は`Xcode`略称だと思われます。Capabilityの追加
以下の+CapabilityからPush NotificationsとBackground Modesを追加してください。

Firebaseの設定
iOSアプリを追加
Firebaseの画面から+アプリの追加を選択しiOSを追加ます。
アプリの登録
iOSバンドルIDはXcodeのSigning画面内にあるBundle Identifierとなります。
設定ファイルのダウンロード
GoogleService-Info.plistをダウンロードし、Xcodeの下記の場所に移動します。

Firebase SDK の追加
何もせず次へを押してスキップします。
初期化コードの追加
何もせず次へを押してスキップします。
次のステップ
何もせずコンソールに進むを押します。
APNs認証キー の登録
Firebaseメニューの歯車からプロジェクトを設定を選択します。

Cloud MessagingのiOSアプリからAPNs認証キーのアップロードを選択します。

Apple Developer ProgramのKeysで作成した.p8ファイルをアップロードし、キーIDは下記のKeysの詳細画面から確認します。

チームIDはApple Developer Program内のIdentifiersにある自動生成された証明をの詳細を開くと下記のようにTeam IDが確認できます。

Flutterの設定
基本的には、下記のサンプルコードを参考にしてもらえれば大丈夫なはずです。
https://github.com/yana1316/flutter_fcm_first_sample
.yaml
pubspec.yamlに追記します。
dependencies:
flutter:
sdk: flutter
firebase_messaging: ^7.0.3 # 追加
main.dart
Firebase用のSDKを用意
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
iOS用 Push通知の許可
「xxxはあなたにプッシュ通知を送信します。よろしいですか?」を表示させるやつです。
/// iOS用 PUSH通知の許可確認
_firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(sound: true, badge: true, alert: true));
FCM用Tokenの取得
FCMサーバーにデバイスID?を送信して、デバイス固有のTokenを取得します。このTokenは、FCMからメッセージを送信するときの宛先となります。
/// iOS用 PUSH通知の許可確認
/// FCM token の取得
_firebaseMessaging.getToken().then((String token) {
assert(token != null);
setState(() {
_token = token;
});
print("token: $_token");
});
メッセージ受診時の処理
FCMからメッセージを受信したさいの処理を記載します。必要最低限の動作はonMessageで確認できます。onLaunchやonResume、onBackgroundMessageなどは設定条件もありますので、詳細はPlugin公式をご確認ください。
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
setState(() {
_message = "onMessage: $message";
});
print("onMessage: $message");
},
/// 省略
);
動作確認
Tokenの取得
Android Studioでシミュレーターを実行すると、画面上にtokenが表示されます。

またAndroid StudioのConsoleにtokenがprintされますのでコピーしておきます。

Firebase Cloud Messagingからの送信テスト
FirebaseのCloud MessageingにあるSend your first messageを開きます。

タイトルやテキストを適当に埋めてテストメッセージを送信ボタンを押します。

表示されたダイアログにコピーしておいた送信先のtokenを貼り付けしテストボタンを押します。

Consoleからの送信テスト
curlが使えるconsoleからも送信テストができます。以下はmacでの例です。
server keyは Fireaseの設定内、Cloud Messagingタブにあるサーバーキーとなります。
project idは Fireaseの設定内、全般タブにあるプロジェクトIDとなります。
以下をconsoleにコピペし、key=${server key}などをkey=hogehogeと置き換えて実行すれば送信されるかと思います。
curl -X POST \
--header "Authorization: key=${server key}" \
--header "project_id: key=${project id}" \
--header Content-Type:"application/json" \
https://fcm.googleapis.com/fcm/send \
-d @- << EOF
{
"to": "${fcm token}",
"notification": {
"body": "curl test"
},
}
EOF
正しく送信されると以下のようなResponseが戻り、シミュレーターにもメッセージが表示されます。
{"multicast_id":7325921480228621614,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1607493418784266%a3c83467a3c83467"}]}
私がハマったポイント
- Xcodeの証明書に不慣れで
Automatically manage signingについて理解できていなかった - APNs証明書で Keys(.p8) でよかったのに、がんばって .p12 を作ってしまった
- シミュレーターではPush通知の受け取りに制約があることを知らなかった
- 開発用証明書(Development)と本番証明書(Distribution)、AdHoc証明書、の違いがわかっていなかった
- iOSではアプリがバックグラウンド時にメッセージを受信しバックグラウンド処理を行うことが難しいことについてについて、しばらくしてから気づいた(今は簡単に出来るのかも?)
まとめ
最低限のPush通知をFCMを利用して送信してみる内容でした。AndroidやiOS開発からFlutterに移動したかたは慣れていると思いますが、初めてのモバイルアプリ開発をFlutterで行う場合、結構な壁になるのかなぁとも思いました。少しでも参考になればと思います。
不明点や間違いなどありましたら、ご質問、ご指摘下さい!
