web-dev-qa-db-fra.com

Firebase Cloud Messaging iOS: Pas de notification Push en arrière-plan

En utilisant la messagerie Cloud plus récente de Firebase avec la méthode swizzling, je parviens à recevoir une charge utile dans la méthode didReceiveRemoteNotification dans mon délégué d’application lorsque mon application est au premier plan . Cependant, je ne reçois aucune sorte de charge utile et didReceiveRemoteNotification ne s'appelle pas lorsque mon application est en arrière-plan , malgré la réponse de l'API indiquant que le message a été envoyé avec succès (voir ci-dessous)
Voici la demande que j’envoie à l’API FCM pour déclencher une notification Push 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"  
 } 
}


avec réponse de la FCM

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

Voici mon code 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.")
            }
        }
    }

}

J'appelle ce code ultérieurement dans mon application pour demander des autorisations.

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

Étant donné que je suis en mesure de recevoir des notifications alors que l'application est au premier plan, je suppose que cela dissiperait tout problème que les certificats de mes apns ne soient pas téléchargés ou que le jeton d'enregistrement soit incorrect. Si ce n'est pas le cas, merci de commenter et je redescendrai dans ce trou de lapin .. Il y a probablement quelque chose de simple que je néglige, mais comment puis-je faire en sorte que les notifications apparaissent lorsque l'application est en arrière-plan? Merci

15
Daniel George

Apparemment, (malgré l'utilisation de la méthode qui devrait le faire automatiquement), vous devez toujours définir le jeton APNS sur l'instance Firebase. Par conséquent, cela signifie que vous devez également implémenter la méthode didRegisterForRemoteNOtificationsWithDeviceToken avec quelque chose comme:

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


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

Comme une note ajoutée. Utiliser "priority":"high" était utile pour tester car il envoyait la notification immédiatement.

10
Daniel George

Suit cette étape après l'obtention du jeton réussi de FCM pour activer l'extraction de données utiles en arrière-plan à l'aide de FCM:

  1. ouvrez Project Navigator> AppCapabilities> Modes d'arrière-plan> rechercher des notifications distantes.

  2. Dans App.delegate, définissez:

    func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
        print("userinfo in background mode on-\(userInfo)")
    
        completionHandler(UIBackgroundFetchResult.newData)
    }
    
  3. Formatez correctement votre charge utile conformément aux directives Apple: entrez la description du lien ici

  4. N'oubliez pas d'ajouter une paire de valeurs de clé: {"content-available":1} Sauf si vous ne pouvez pas récupérer les données utiles en arrière-plan.

maintenant, essayez d'envoyer à nouveau la notification en utilisant le jeton FCM. Bonne codage

0
Vinayak Pal

Assurez-vous que vous avez ajouté "content_available": true dans la charge JSON. Sinon, vous ne recevrez pas de notification Push en arrière-plan.

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

De la même manière que la solution de Daniel George, je pourrais résoudre mon problème avec:

Messaging.messaging().apnsToken = deviceToken

FirebaseInstanceID 2.0.8, FirebaseMessaging 2.0.8

0
Colibri

Le comportement souhaité, du moins pour mon application, est l'arrivée d'une notification Push, dans laquelle le contenu de la notification PN (Push Notification) doit s'afficher dans une page souhaitée de l'application.

J'ai trois états d'application différents où un PN peut arriver: (Bien sûr, cela dépend de votre implémentation, mais vous devriez avoir une idée de la façon dont Apple traite le PN dans ces états)

(le comportement est déterminé par Apple!)

1) l'application est au premier plan:

  • PN reçu
  • apparaît dans le centre de notification (vous pouvez cliquer dessus ou pas - peu importe)
  • le badge sera mis à jour 
  • PN est disponible dans la page souhaitée

Dans ce cas, l'application always traite le PN.

2) l'application est en arrière-plan:

  • PN reçu
  • apparaît dans le centre de notification (vous pouvez cliquer dessus ou pas - peu importe)
  • le badge sera mis à jour
  • PN est disponible dans la page souhaitée

Dans ce cas, l'application always traite le PN.

3) l'application est tuée/fermée:

  • PN reçu
  • apparaît dans le centre de notification 
  • maintenant il y a trois manières possibles

    1. glisser la notification loin -> PN seraPAStraité par l'application

    2. ouvrez l'application via l'icône du lanceur directement -> PN seraPAStraité par l'application

    3. cliquez sur la notification -> PN sera traité par l'application

Bien sûr, cela dépend de votre implémentation, car dans le cas "3. Ouvrez l'application directement via l'icône du lanceur", vous pouvez simplement récupérer tous les PN au démarrage de l'App via une API supplémentaire. MAIS vous devriez avoir une idée de la façon dont Apple empêche le traitement du PN dans certains cas.

J'espère que cela aide quelqu'un!

0
Manuel Schmitzberger