web-dev-qa-db-ja.com

Firebase Cloud Messaging iOS:バックグラウンドプッシュ通知なし

アプリがforegroundedの場合、メソッドswizzlingで新しいFirebaseクラウドメッセージングを使用すると、アプリデリゲートのdidReceiveRemoteNotificationメソッドでペイロードを正常に受信できます。ただし、アプリがbackgroundedの場合、メッセージが正常に送信されたというAPI応答にもかかわらず(以下を参照)、ペイロードが何も取得されず、didReceiveRemoteNotificationが呼び出されません。
ここに、プッシュ通知をトリガーするためにFCM apiに送信するリクエストがありますhttps://fcm.googleapis.com/fcm/send

{
"to": "{valid-registration-token}",
"priority":"high", //others suggested setting priority to high would fix, but did not
  "notification":{
      "body":"Body3",
      "title":"test"  
 } 
}


FCMからの応答あり

{
      "multicast_id": 6616533575211076304,
      "success": 1,
      "failure": 0,
      "canonical_ids": 0,
      "results": [
        {
          "message_id": "0:1468906545447775%a4aa0efda4aa0efd"
        }
      ]
    }

これが私のappDelegateコードです

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        Fabric.with([Crashlytics.self])
        FIRApp.configure()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.tokenRefreshNotification),
                                                         name: kFIRInstanceIDTokenRefreshNotification, object: nil)
        return true
    }



    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
        // Let FCM know about the message for analytics etc.
        FIRMessaging.messaging().appDidReceiveMessage(userInfo)

        // Print full message.
        print("%@", userInfo)

        // handle your message

//        let localNotification = UILocalNotification()
//        localNotification.fireDate = NSDate()
//        let notification = userInfo["notification"]!
//        localNotification.alertBody = notification["body"] as? String
//        localNotification.alertTitle = notification["title"] as? String
//        localNotification.timeZone = NSTimeZone()
//        application.scheduleLocalNotification(localNotification)

    }

    func tokenRefreshNotification(notification: NSNotification) {
        let refreshedToken = FIRInstanceID.instanceID().token()!
        print("InstanceID token: \(refreshedToken)")
        LoginVC.registerForPushNotifications()
        connectToFcm()
    }


    //foreground messages
    func applicationDidBecomeActive(application: UIApplication) {
        connectToFcm()
    }

    // [START disconnect_from_fcm]
    func applicationDidEnterBackground(application: UIApplication) {
        FIRMessaging.messaging().disconnect()
        print("Disconnected from FCM.")
    }


    func connectToFcm() {
        FIRMessaging.messaging().connectWithCompletion { (error) in
            if (error != nil) {
                print("Unable to connect with FCM. \(error)")
            } else {
                print("Connected to FCM.")
            }
        }
    }

}

アプリの後でフローでこのコードを呼び出して、権限を要求します

static func registerForPushNotifications() {
    let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
            UIApplication.sharedApplication().registerUserNotificationSettings(settings)
            UIApplication.sharedApplication().registerForRemoteNotifications()
}

アプリがフォアグラウンドになっているときに通知を受け取ることができるので、これは私のapns証明書がアップロードされていない、または登録トークンが正しくないというすべての懸念を和らげると思います。そうでない場合は、コメントしてください。そのうさぎの穴をもう一度下ります。見落としている簡単なものがあると思いますが、アプリのバックグラウンド中に通知を表示するにはどうすればよいですか?ありがとう

15
Daniel George

どうやら(自動的に行われるはずのメソッドのスウィズリングを使用しているにもかかわらず)、FirebaseインスタンスにAPNSトークンを設定する必要があります。したがって、これはdidRegisterForRemoteNOtificationsWithDeviceTokenメソッドも次のように実装する必要があることを意味します

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {


        // set firebase apns token
        FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
}

追加のメモとして。 "priority":"high"を使用すると、通知がすぐに送信されるため、テストに役立ちました。

11
Daniel George

ダニエルジョージのソリューションと同様に、次の方法で問題を修正できます。

Messaging.messaging().apnsToken = deviceToken

FirebaseInstanceID 2.0.8、FirebaseMessaging 2.0.8

1
Colibri

少なくとも私のアプリにとって望ましい動作は、PN(プッシュ通知)のコンテンツがアプリの必要なページに表示されるプッシュ通知の到着です。

PNが到達できるアプリの状態は3つあります(もちろん、実装によって異なりますが、Appleがこれらの状態でPNを処理する方法)

(動作はAppleによって決定されます!)

1)アプリはフォアグラウンドにあります:

  • 受け取ったPN
  • 通知センターにポップアップします(クリックするかしないかは問題ありません)
  • バッジが更新されます
  • PNは目的のページで利用できます

この場合、アプリalwaysはPNを処理します

2)アプリはバックグラウンドです:

  • 受け取ったPN
  • 通知センターにポップアップします(クリックするかしないかは問題ありません)
  • バッジが更新されます
  • PNは目的のページで利用できます

この場合、アプリalwaysはPNを処理します

)アプリが強制終了/クローズされました:

  • 受け取ったPN
  • 通知センターにポップアップします
  • 今、3つの可能な方法があります

    1. 通知をスワイプして離れる-> PNは[〜#〜] not [〜#〜]アプリによって処理されます

    2. ランチャーアイコンを介してアプリを直接開く-> PNは[〜#〜] not [〜#〜]アプリによって処理されます

    3. 通知をクリックします-> PNはアプリによって処理されます

この場合、ユーザーが通知をタップしてアプリを開かないを実行すると、通知データを取得する方法がありませんがあります。

アプリの状態から独立するには、特定のデータをリクエストできるサーバーをセットアップする必要があります。例えば。すべての通知を表示するビューがあり、特定のデータを要求するにはAPIが必要です。 Pushnotificationの受信メソッドでデータを処理しないでください。

それが誰かを助けることを願っています!

FCMからトークンを取得した後、次の手順に従って、FCMを使用したバックグラウンドペイロードデータのフェッチを有効にします。

  1. project Navigator> AppCapabilities>バックグラウンドモードを開き、リモート通知を確認します。

  2. App.delegateで以下を定義します。

    func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
        print("userinfo in background mode on-\(userInfo)")
    
        completionHandler(UIBackgroundFetchResult.newData)
    }
    
  3. Appleガイドライン: ここにリンクの説明を入力 に従ってペイロードを正しくフォーマットしてください==

  4. キーと値のペアを追加することを忘れないでください:{"content-available":1}バックグラウンドでペイロードを取得できない場合を除きます。

fCMトークンを使用して、もう一度通知を送信してみてください。幸せなコーディングを

0
Vinayak Pal

JSONペイロードに "content_available":trueが追加されていることを確認してください。そうしないと、バックグラウンドモードでプッシュ通知を取得できません。

"notification" : {
            "body" : "this is body",
            "title" : "this is title"
}
"content_available" : true
0
Rupom