Firebaseでサーバレスアプリをサクッと作ってみる① ~Cloud MessagingでPush通知実装~
Firebaseを使ってアプリを作る
イメージはこんな感じ。二時間もあれば画像アップロードもこれに加えて画像のアップロードも実装できる。
Firebaseがサクッとアプリを作るのにめちゃくちゃ便利なので、その手順を書いていきたい。ここで実装する機能としては、匿名ログイン(ログイン・サインアップをさせずに認証情報を与える)、DB(Firestore)に書き込み・読み取り、DBの書き込みに応じてプッシュ通知を飛ばす、のを想定する。こういった機能を実装しようとすると一日で1人でやるにはキツイが、Firebaseを利用するとサクッと数時間もあればできてしまう。たしかに悪意のあるユーザからの書き込みをどうケアするのか(基本的にクライアントからの情報は信用してはいけない)といったことは別途考える必要はあるが、プロトタイピングするにはモッテコイなサービスだと思う。
以下、利用するサービスや構成である。
- クライアント:Swift
- バックエンド:Firebase
- データベース:Cloud Firestore・Pring
- プッシュ通知:Cloud Messaging・Cloud Functions
- 認証:Firebase Auth
長くなりそうなので、本記事では、プロジェクトを新規作成してプッシュ通知を実機に送るところまで実装していく。Firebaseを利用したプッシュ通知の実装の参考にもなればいいなという気持ちもある。
1. プロジェクトのセットアップ
Xcodeで新規プロジェクトの作成をする。
次にここでFirebaseのプロジェクトを作成する。
続いて、XcodeにFirebaseをセットアップしていく。
BundleIDやアプリのニックネームを入力して次に進むと、 GoogleService-Info.plist
が発行されるので、それをXcodeにドラッグアンドドロップして突っ込む。
最後に、CocoaPodsを使ってFirebaseをプロジェクトにインストールする。
$ cd /project // 自分のproject rootに行く $ pod init $ vim Podfile // # Pods for FirebaseSampleの下の行に pod 'Firebase/Core' を付け足す $ pod install
pod install
が完了すると FirebaseSample.xcworkspace
ができているのでそれをダブルクリックしてXcodeを開く。 AppDelegate.swift
を開いて以下のように import Firebase
と FirebaseApp.configure()
の2行を追加する。
import UIKit import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() return true } }
Xcodeで実行すると以下の画面になり、Firebaseのセットアップが完了する。
2. プッシュ通知の設定をしていく
プッシュ通知の証明書には.p12ではなく.p8を使う。 .p8はHTTP2に対応しており、 .p12ではあった有効期限もなく、.p12ファイルの作成よりもずっと簡単 だ。これからは.p12ではなく.p8を利用する方が良さそうでFirebaseも.p8を推奨している。ただし、AWSのAmazon SNSやツールによってはまだ.p8に対応していないようなので注意が必要そう。
Xcodeに戻って、Capabilitiesで Push Notifications
と Background Modes
をONにして Remote Notifications
にチェックを入れておく。
続いて、AppleのDev CenterでApp IDsを開くと、先ほど作成したプロジェクトが XC hoge fuga FirebaseSample
という名前で追加されているので詳細を開く。すると、Push Notificationsの状態がConfigurableになっているのでEditを選択する。DevelopmentとDistribution両方の証明書を作成していくが、そのためにはCSRファイルが必要になるので、まずそれの作成をする(と言ってもすごく簡単)。一旦、以下の画面のまま、キーチェーンアクセスを開く。
キーチェーンアクセスを開き、 キーチェーンアクセス
> 証明書アシスタント
> 認証局に証明書を要求
をクリックする(画像は英語の設定ですが同じです)。
ユーザーのメールアドレス
を入力し、 通称
はそのまま、 CAのメールアドレス
は空欄のままで良い。 要求の処理
は ディスクに保存
を選択し 鍵ペア情報を設定
にチェックを入れ、 続ける
をクリックする。
鍵の情報が以下のように表示されるが特にいじらずそのまま進めるとCSRファイルがダウンロードできる。
再び、Dev Centerに戻って、 Create Certificate
をクリックして、作成したばかりのCSRファイルをアップロードする。
すると、.cerファイルが生成されるのでダウンロードし、クリックする。クリックしても何も起こらないように見えるがキーチェーンアクセスにセットされるので問題ない。DevelopmentとDistribution両方とも同じCSRファイルで設定する。Dev CenterでApp IDsの当該プロジェクトを確認して以下のように、Push Notificationsが緑になっていればOK。
Dev CenterのKeysという欄から.p8ファイルを作成する。Keysを開いて右上の+をクリックする。画像の方に入力して次へ進む。
下の画像のようになれば成功で、.p8ファイルをダウンロードし、Key IDも記録しておく。.p8ファイルはここでしかダウンロードできないので紛失しないように注意しなければならない。
次に、Firebaseのコンソールを開いてプッシュの証明書をセットしていく。まず、設定のクラウドメッセージングを開く。
以下の画像にあるAPNs認証キーが.p8ファイルのことである。.p8ファイルを生成した時に発行されたKey IDとMembershipのページのTeamIDを入力する。
これでプッシュ通知まわりの設定は完了したので、あとはコードを書いていく。といっても書くのは主に AppDelegate.swift
くらいある。
iOSプッシュ通知の仕組みについては以下が参考になる。
3. プッシュ通知の実装をしていく
Podfile
に pod 'Firebase/Messaging'
を追加して、 pod install
を実行する。 AppDelegate.swift
を以下のように実装する。この中で各デバイスのFCMトークンを取得できる。このトークンに向かってFirebaseでプッシュ通知を送ることができるので、後々、Firestoreの書き込みに応じて任意のユーザにプッシュ通知を送る場合はこのFCMトークンが必要になってくる。ここでは一旦printするだけにしている。
import UIKit import Firebase import FirebaseMessaging import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() // 以下を追加する application.registerForRemoteNotifications() Messaging.messaging().delegate = self UNUserNotificationCenter.current().delegate = self return true } } // MARK: - UNUserNotificationCenterDelegate extension AppDelegate : UNUserNotificationCenterDelegate { // 通知を受け取った時に(開く前に)呼ばれるメソッド func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo // for analytics // Messaging.messaging().appDidReceiveMessage(userInfo) if let messageID = userInfo["gcm.message_id"] { print("Message ID: \(messageID)") } completionHandler([.alert]) } // 通知を開いた時に呼ばれるメソッド func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo if let messageID = userInfo["gcm.message_id"] { print("Message ID: \(messageID)") } completionHandler() } } // MARK: - MessagingDelegate extension AppDelegate: MessagingDelegate { func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) { print("Firebase registration token: \(fcmToken)") } func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) { print("Received data message: \(remoteMessage.appData)") } }
続いて、 ViewController.swift
にプッシュ通知の許可ダイアログを表示するように実装する。コードは以下のようになる。
import UIKit import UserNotifications class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // プッシュ通知の許諾ダイアログを出したいタイミングで呼んであげる. 必ずしもここじゃなくても良い let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in print("push permission finished") } } }
実行すると画像のようにプッシュ通知許可のダイアログが表示される。
ここまで来たので試しに取得したFCMトークンに対してプッシュ通知を送ってみる。Xcodeのデバッグで吐かれたFCMトークンをコピーして、以下の画像のようにFirebaseのコンソールのCloud Messagingの項目からプッシュ通知を送信してみる。
ちゃんと届いたことが確認できた。
ソースコードはここにあります。
つづく。次は、Firestoreにデータを書き込んでそれをトリガーにしてプッシュ通知が届くように実装していく。