xyk blog

最近は iOS 開発の記事が多めです。

Firebase Cloud Messaging によるプッシュ通知をバックグラウンドでも受け取る

Swift version 5.0.1
iOS11

Firebase Cloud Messaging でアプリがバックグラウンドでもプッシュ通知を受け取る方法について。
APNs ペイロードcontent-available: 1を含める必要あり。
これが含まれることでアプリがバックグラウンドであっても
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
メソッドが呼ばれるようになる。またフォアグラウンドでも同様に呼ばれる。
この引数のクロージャであるfetchCompletionHandlerはメソッドの開始から 30 秒以内に実行する必要がある。
アプリが未起動の場合にはこのメソッドは呼ばれない。

Xcode 設定

Xcode

  • Capabilities -> Background Modes -> Remote notifications
  • Capabilities -> Push Notifications

にチェックを入れる。

f:id:xyk:20190830161336p:plain f:id:xyk:20190830161205p:plain

FCM Token 取得コード

import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        FirebaseApp.configure()
        Messaging.messaging().delegate = self
        return true
    }
}

extension AppDelegate: MessagingDelegate {
    // FCMトークン取得
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")
    }
}

通知受信時のハンドリング

// AppDelegate
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        if let foo = userInfo["foo"] as? String {
            print("foo: \(foo)") // -> bar
        }
        completionHandler(.newData)
    }

cURL で疎通確認

$ curl --header "Content-Type: application/json" \
--header "Authorization: key={サーバーキー}" \
https://fcm.googleapis.com/fcm/send \
-d '{"notification": {"body": "Hello from curl via FCM!", "sound": "default"},
"priority": "high",
"content_available": true,
"data" {
  "foo": "bar"
},
"to": "{FCMトークン}"}'

サーバーキーは FIrebase 管理画面から取得、FCMトークンは上記 Delegate で取得したトークン。

f:id:xyk:20190829154049p:plain

content_available パラメータは必須。

Firebase Cloud Messaging の HTTP プロトコル

iOS では、このフィールドを使用して APNs ペイロードで content-available を表します。通知やメッセージの送信時にこのフィールドが true に設定されている場合、非アクティブなクライアント アプリのスリープ状態が解除されます。また、メッセージは FCM 接続サーバーではなく APNs を介して、サイレント通知として送信されます。APNs のサイレント通知の配信は保証されておらず、ユーザーが [低電力モード] をオンにする、アプリを強制終了するなどの要因によって結果が異なる場合があることに注意してください。

data パラメータにはカスタムのデータを入れられる。


サイレントプッシュ通知について

上のバックグラウンド受信と同様に、content-available キーに 1 を指定し、かつ alert.bodysoundbadge の各キーを除外することでサイレントプッシュ通知となる。
サイレントプッシュ通知を受信すると、通知センターは表示されず application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
が呼び出される。
通知センターは表示しないのでユーザに通知許諾を得ずとも使用可能。

cURLでサイレントプッシュ通知

$ curl --header "Content-Type: application/json" \
--header "Authorization: key={サーバーキー}" \
https://fcm.googleapis.com/fcm/send \
-d '{
"priority": "high",
"content_available": true,
"data" {
  "foo": "bar"
},
"to": "{FCMトークン}"}'

参考:
Google Developers Japan: iOS で Firebase Cloud Messaging をデバッグする
https://developers-jp.googleblog.com/2017/02/debugging-firebase-cloud-messaging-on.html
プッシュメッセージのカスタマイズ
https://docs.kii.com/ja/guides/cloudsdk/ios/managing-push-notification/push-techinology/message-customize/