wake-up-neo.com

FCM-Hintergrundbenachrichtigungen funktionieren nicht in iOS

Ich habe ein Problem mit der FCM-Benachrichtigung unter iOS.

Ich erhalte Benachrichtigungen mit Erfolg, wenn sich meine App im Vordergrund befindet (der Rückruf didReceiveRemoteNotification in appdelegate wird ausgelöst), aber ich erhalte keine Benachrichtigungen, wenn sich die App im Hintergrund befindet (ich sehe nichts im Benachrichtigungsbereich von iOS).

Ich denke, das Problem liegt im Format der Nachricht, die von FCM gesendet wird. Die Json, die mein Server an FCM gesendet hat, hat folgendes Format:

{  
   "data":{  
      "title":"mytitle",
      "body":"mybody",
      "url":"myurl"
   },
   "notification":{  
      "title":"mytitle",
      "body":"mybody"
   },
   "to":"/topics/topic"
}

Wie Sie sehen, gibt es in meinem json zwei Blöcke: einen Benachrichtigungsblock (zum Empfangen von Benachrichtigungen im Hintergrund) und einen Datenblock (zum Empfangen von Benachrichtigungen im Vordergrund).

Ich kann nicht verstehen, warum Benachrichtigungen im Hintergrund nicht empfangen werden .. Meine Zweifel beziehen sich auf die Reihenfolge der Blöcke (ist ein Problem, wenn ich den "Daten" -Block vor den "Benachrichtigungs" -Block stelle?).

EDIT: Weitere Informationen zum Problem.

Das ist mein appdelegate.Swift:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
{
    var window: UIWindow?


    // Application started
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
    {
        let pushNotificationSettings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        application.registerUserNotificationSettings(pushNotificationSettings)
        application.registerForRemoteNotifications()

        FIRApp.configure()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "tokenRefreshNotification:", name: kFIRInstanceIDTokenRefreshNotification, object: nil)

        return true
    }




    // Handle refresh notification token
    func tokenRefreshNotification(notification: NSNotification) {
        let refreshedToken = FIRInstanceID.instanceID().token()
        print("InstanceID token: \(refreshedToken)")

        // Connect to FCM since connection may have failed when attempted before having a token.
        if (refreshedToken != nil)
        {
            connectToFcm()

            FIRMessaging.messaging().subscribeToTopic("/topics/topic")
        }

    }


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


    // Handle notification when the application is in foreground
    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
            // If you are receiving a notification message while your app is in the background,
            // this callback will not be fired till the user taps on the notification launching the application.
            // TODO: Handle data of notification

            // Print message ID.
            print("Message ID: \(userInfo["gcm.message_id"])")

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


    // Application will enter in background
    func applicationWillResignActive(application: UIApplication)
    {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }



    // Application entered in background
    func applicationDidEnterBackground(application: UIApplication)
    {
        FIRMessaging.messaging().disconnect()
        print("Disconnected from FCM.")
    }



    // Application will enter in foreground
    func applicationWillEnterForeground(application: UIApplication)
    {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }



    // Application entered in foreground
    func applicationDidBecomeActive(application: UIApplication)
    {
        connectToFcm()

        application.applicationIconBadgeNumber = 0;
    }



    // Application will terminate
    func applicationWillTerminate(application: UIApplication)
    {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }


}

Die einzige Möglichkeit, Nachrichten im Vordergrund zu empfangen, besteht darin, die Methode Swizzling zu deaktivieren und FirebaseAppDelegateProxyEnabled in meiner info.plist auf NEIN zu setzen.

In diesem Fall sagt die FCM-Dokumentation, dass ich in meinem appdelegate.Swift zwei Methoden implementieren muss:

 - FIRMessaging.messaging().appDidReceiveMessage(userInfo)  in didReceiveRemoteNotification callback
 - FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Sandbox) in didRegisterForRemoteNotificationsWithDeviceToken callback

Wenn ich diese Funktionen implementiere, werden jedoch keine Nachrichten mehr angezeigt, selbst wenn die App im Vordergrund steht.

Ich weiß, dass das sehr seltsam ist. 

EDIT 2:  

Wenn sich die App im Hintergrund befindet, wird die Benachrichtigung nicht empfangen, aber wenn ich meine App öffne, wird dieselbe Benachrichtigung sofort empfangen (die Methode didReceiveRemoteNotification wird ausgelöst).

31
Mark O' Brian

Wenn Sie angenommen haben, dass Sie alles korrekt eingerichtet haben, sollte das Setzen der priority der Nachricht von normal auf high sofort erscheinen. Dies liegt daran, wie iOS Benachrichtigungen bündelt und diese verarbeitet. Informationen zur Priorität von FCM-Benachrichtigungen finden Sie hier . Bitte beachten Sie, dass Sie high nicht wirklich in der Produktion verwenden sollten, es sei denn, es gibt einen guten Grund dafür, da dies zu einer Batteriestrafe führt.

Hier ist die Referenz aus Apples Dokumente

Die Priorität der Benachrichtigung. Geben Sie einen der folgenden Werte an:

10 - Senden Sie die Push-Nachricht sofort. Benachrichtigungen mit dieser Priorität muss auf dem Zielgerät einen Alarm, einen Ton oder ein Badge auslösen. Es ist ein Fehler bei Verwendung dieser Priorität für eine Push-Benachrichtigung, die nur .__ enthält. der inhaltsverfügbare Schlüssel.

5 - Senden Sie die Push-Nachricht zu einem Zeitpunkt, der die Leistung berücksichtigt Überlegungen zum Gerät. Benachrichtigungen mit dieser Priorität können gruppiert und in Bursts geliefert werden. Sie sind gedrosselt und in einigen Fälle werden nicht geliefert. Wenn Sie diesen Header nicht angeben, setzt der APNs-Server die Priorität bis 10.

23
Chris

Sie müssen die content_available-Eigenschaft wie folgt auf true setzen:

{  
   "data":{  
      "title":"mytitle",
      "body":"mybody",
      "url":"myurl"
   },
   "notification":{  
      "title":"mytitle",
      "body":"mybody",
      "content_available": true
   },
   "to":"/topics/topic"
}

In diesem Abschnitt befindet sich ein blaues Hinweisfeld, das Folgendes angibt: https://firebase.google.com/docs/cloud-messaging/concept-options#notifications

17
Keith Holliday

Priorität und content_available (wie in anderen Antworten erwähnt) sind die Schlüsselelemente, um sicherzustellen, dass Sie die Benachrichtigungen erhalten. Tests haben interessante Ergebnisse gezeigt, daher wollte ich sie hier teilen.

Testergebnisse: Swift 3, Xcode 8, iOS 10

Priorität = "hoch" => "sofort" (innerhalb offensichtlicher Netzwerkverzögerungen) Empfang der Nachricht.

Priorität = "normal" => verschiedene Ergebnisse (im Allgemeinen schnell, aber offensichtlich langsamer als "hoch")

content_available = true in den Benachrichtigungen (keine Nutzlastnachricht)

  • Vordergrund = erwartete Daten
  • Hintergrund = erwartete Daten (beim Öffnen der App)

content_available = true in der obersten Ebene (keine Nutzlastnachricht)

  • Vordergrund = erwartete Daten
  • Hintergrund = erwartete Daten (beim Öffnen der App)

content_available = true in den Benachrichtigungen (mit Nachricht {title/body})

  • Vordergrund = ZWEIMAL erhaltene Daten
  • Hintergrund = ZWEIMAL erhaltene Daten (beim Öffnen der App) 

content_available = true in der obersten Ebene (mit Nutzlastnachricht)

  • Vordergrund = ZWEIMAL erhaltene Daten
  • Hintergrund = ZWEIMAL erhaltene Daten (beim Öffnen der App)

SCHLUSSFOLGERUNGEN:

  1. Während Priorität eine mögliche Ursache dafür ist, dass Nachrichten nicht empfangen werden, ist der WICHTIGSTE Faktor, dass Sie entweder 'content_available' oder eine Nutzlastnachricht haben müssen.
  2. content_available MUSS für reine Nutzdaten verwendet werden (ohne dass keine Nachricht gesendet wird).
  3. content_available SOLLTE NICHT für Payloads verwendet werden, die Nachrichten enthalten, da dadurch doppelte Nachrichten von FCM gesendet werden.
  4. Kein Unterschied in der Verwendung von content_available auf der obersten Ebene oder in den Benachrichtigungen gefunden.

BEARBEITEN: Zusätzliche Testergebnisse: - Wenn Sie einen msg-Titel haben, MÜSSEN Sie einen msg-Body haben oder keine Benachrichtigung erhalten. 

Der seltsame Teil davon ist, dass Sie das Vibrieren, das Abzeichen und den Ton erhalten, aber das Benachrichtigungsfeld wird nur angezeigt, wenn Sie einen Körper sowie den Titel haben.

9
CFP Support

Möglicherweise müssen Sie die Push-Benachrichtigungsberechtigung hinzufügen. Gehen Sie dazu zu Ihren Zieleinstellungen, klicken Sie auf "Capabilities" und aktivieren Sie "Push Notifications".

 Target Capabilities

9
astromme

wenn Sie direkte FCM-Kanalmeldungen verwenden, können Sie keine Benachrichtigung im Hintergrund erhalten 

dies ist ein Absatz aus Firebase-Dokument :

Wenn der direkte Kanal aktiviert ist, verwendet das FCM-Backend eine zuverlässige Nachrichtenwarteschlange, um ausstehende Nachrichten zu verfolgen, wenn sich die App im Hintergrund befindet oder geschlossen ist. Wenn die App in den Vordergrund wechselt und die Verbindung wiederhergestellt ist, sendet der Kanal automatisch ausstehende Nachrichten an den Client, bis er eine Bestätigung vom Client erhält.

sie können die FCM-APNs-Schnittstelle verwenden, um Benachrichtigungen sowohl im Vordergrund als auch im Hintergrund zu erhalten

1
hamed moosaei

-Für FCM, wenn sich die Anwendung im Hintergrund oder Vordergrund befindet und die OS <10 Anwendung (_: didReceiveRemoteNotification :) -Methode ausgelöst wird.

-Wenn die Anwendung im Vordergrund steht und das Betriebssystem => 10 ist UserNotificationCenter: willPresentNotification: withCompletionHandler: Die Methode wird ausgelöst.

- Wenn Sie eine Datennachricht ohne Benachrichtigungskomponente senden: Die Anwendung (_: DidReceiveRemoteNotification :) wird ausgelöst.

- Wenn Sie eine Datennachricht mit Benachrichtigungskomponente senden: UserNotificationCenter: willPresentNotification: withCompletionHandler: Die Methode wird ausgelöst.

0