Firebaseを使用してiOSアプリにプッシュ通知を実装する

#はじめに
Firebaseの`Cloud Messaging`を使用してアプリにプッシュ通知を実装します。

#前提条件
[Apple Developer Program](https://developer.apple.com/jp/programs/how-it-works/)の登録と、[Firebase](https://firebase.google.com/docs/ios/setup?hl=ja)を導入していること前提で書いていきます。

#プッシュ通知の仕組み
iOSの場合、Appleが提供しているプッシュ通知サービス[APNs(Apple Push Notification Service)](https://ja.wikipedia.org/wiki/Apple_Push_Notification_Service)を介して
プッシュ通知を配信しています。

![push_Notification.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/93c1d9e3-e7d2-7629-3218-1485e1e91bdd.png)
[出典：【Swift】iOSアプリにプッシュ通知を実装したサンプルアプリを作ってみた
](https://qiita.com/natsumo/items/ebba9664494ce64ca1b8)

このサービスのおかげで`Cloud Messaging`からプッシュ通知が送れるという訳です。

#実装する前に
まずは、`Cloud Messaging`を使用するために必要なライブラリをインストールしましょう。

因みに自分はSPMでインストールしました。
[Swift Package Manager (SwiftPM) を使ってみよう　~導入編~](https://qiita.com/gurensouen/items/f24d868bc6f3be2a3134)

#実装

##・Capabilityを設定する

まずはプッシュ通知に必要な`Capabilityを設定`しましょう。

#####1.TARGETS > Signing & Capabilities > + Capability をクリックする
#####2.Background ModesとPush Notificationsを追加する
#####3.Background Modes内のRemote notifiationsにチェックする

以上の流れを終えると、プロジェクト内に`プロジェクト名.entitlements`ファイルが追加されます。
![スクリーンショット 2021-03-15 14.57.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/eaadf57c-354b-2be8-66c1-68e4d094cd8b.png)

このファイルは、`プッシュ通知の登録時に開発環境と本番環境のどちらのAPNsを使用するかを自動的に指定`します。
[APS Environment Entitlement](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment)

##・APNs認証キーを発行する
APNsを介してCloud Messagingに接続するには`APNs認証キー`を発行して
`Firebaseにアップロード`しなくてはいけません。

#####1.[Apple Developer Account](https://developer.apple.com/account) > Certificates, Identifiers & Profiles > Keys > Keys＋をクリックする
#####2.ページ内でKey Nameを入力 > Apple Push Notifications service (APNs)をチェック > continueをクリックする
#####3.APNs認証キーが発行されたらダウンロードする

これでFirebaseにアップロードする`APNs認証キー`が取得できました。

##・Firebaseプロジェクト内でAPNs認証キーをアップロードする

それでは、APNs認証キーをFirebaseにアップロードしましょう。

#####1.「プロジェクトの概要」の左にある歯車マークから「プロジェクトを設定」をクリックする
#####2.ページ上部にあるCloud Messaging > iOSアプリの構成 > APNs認証キーからアップロードする
#####3.APNs認証キーをアップロードする際に必要なキーIDとチームIDを入力してアップロードを完了させる

キーIDは、Apple Developer AccountのKeys > 自分のAPNs認証キー > `Key ID`から確認できます。

チームIDは、Apple Developer AccountのIdentifiers > 自分のプロジェクト > `App ID Prefix`から確認できます。
 
##・実装コードを書く
必要最低限のコードのみを書きますのでご了承下さい。

```swift
import UIKit
import Firebase

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Coloud Messagingのデリゲート
        Messaging.messaging().delegate = self

        // 通知関連のアクションを処理
        UNUserNotificationCenter.current().delegate = self

        // 通知の許可をユーザーにリクエストする
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
            if let error = error {
                print(error.localizedDescription)
                return
            }
            if granted {
                // aregisterForRemoteNotificationsは必ずメインスレッドで実行する
                DispatchQueue.main.async {
                    // Appleプッシュ通知サービスを介してリモート通知を受信するための登録を行う
                    application.registerForRemoteNotifications()
                }
            }
        }
        return true
    }
}

extension AppDelegate: UNUserNotificationCenterDelegate {
    // アプリがフォアグラウンドで通知を受け取ったときに呼ばれる
        func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
            let userInfo = notification.request.content.userInfo
            print("========== Print full message =========")
            print(userInfo)
            print("===============")

            // プッシュ通知の表示方法を決める
            completionHandler([.banner, .sound, .badge])
        }
}
extension AppDelegate: MessagingDelegate {
    // FCMトークンが利用可能になったり、更新されたりすると呼ばれる
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("===============")
        print("Firebase registration token: \(String(describing: fcmToken))")
        print("===============")
    }
}
```
因みにiOS10以降なら上記のコードでOKですが、`iOS10未満だと実装コードが変わってきます`。
[iOS で Firebase Cloud Messaging クライアント アプリを設定する | Firebase](https://firebase.google.com/docs/cloud-messaging/ios/client?hl=ja#register_for_remote_notifications)

##・プッシュ通知を送る
Firebaseプロジェクト内の`Cloud Messaging`からプッシュ通知を送りましょう。

テスト送信をしたい場合は、`テスト メッセージを送信`から送ることができます。

Firebaseのプロジェクト上でプッシュ通知を送ると`開発・本番用関係なく送信`されますので
開発用ではこちらでプッシュ通知を送りましょう。

![スクリーンショット 2021-03-15 15.58.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/f40aeb03-f2cd-0a96-14cf-7e3e6c20abe7.png)

`テスト メッセージを送信`をクリックし、`FCM登録トークンを追加`を入力すると
テスト送信を端末に送ることが出来ます。
![スクリーンショット 2021-03-15 16.01.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/2ec08eff-5982-1bdc-7f37-3a3ad79b752f.png)

`FCM登録トークン`は先ほど記述したデリゲートメソッドから吐き出されます。

```swift
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("===============")
        print("Firebase registration token: \(String(describing: fcmToken))")
        print("===============")
    }
```

以下のようなプッシュ通知が端末に送られてきたら成功です。
![IMG_6625.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/d907cc00-68f8-6440-bd0e-e89b9e4f025e.jpeg)

#おわりに
画像や動画もプッシュ通知と一緒に送ることができますが、調べてみると難しそうでした。

もし、実装できたらQiitaにまとめようと思います。

#参考
[Firebase Cloud Messagingを使ってアプリに通知機能を実装する](https://qiita.com/gdate/items/deb454b6342f81e0a270#appdelegateswift%E3%81%AB%E9%80%9A%E7%9F%A5%E3%82%92%E5%8F%97%E3%81%91%E5%8F%96%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E5%87%A6%E7%90%86%E3%82%92%E8%BF%BD%E5%8A%A0)
[Push Notifications with Firebase iOS Swift 5 & Xcode 11.5 | Youtube](https://www.youtube.com/watch?v=vvq0etotS8M)