Mit dem neueren Firebase-Cloud-Messaging mit der Methode swizzling kann ich erfolgreich eine Nutzlast in der didReceiveRemoteNotification
-Methode in meinem App-Delegaten empfangen, wenn meine App vordergrundig ist. Ich bekomme jedoch keine Art von Nutzlast und didReceiveRemoteNotification
wird nicht aufgerufen, wenn meine App backgrounded ist, trotz der Antwort der API, dass die Nachricht erfolgreich gesendet wurde (siehe unten)
Hier ist die Anforderung, die ich an die FCM-API sendet, um eine Push-Benachrichtigung auszulösen. 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"
}
}
mit Antwort von FCM
{
"multicast_id": 6616533575211076304,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1468906545447775%a4aa0efda4aa0efd"
}
]
}
Hier ist mein appDelegate-Code
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.")
}
}
}
}
Ich rufe diesen Code zu einem späteren Zeitpunkt in meiner App auf, um nach Berechtigungen zu fragen
static func registerForPushNotifications() {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()
}
Da ich in der Lage bin, Benachrichtigungen zu erhalten, während die App im Vordergrund steht, gehe ich davon aus, dass dadurch alle Bedenken beseitigt werden, dass meine Apns-Zertifikate nicht hochgeladen werden oder dass das Registrierungstoken falsch ist. Wenn dies nicht der Fall ist, kommentieren Sie bitte, und ich werde dieses Kaninchenloch wieder hinuntergehen ... Es gibt wahrscheinlich etwas einfaches, das ich übersehe, aber wie kann ich die Benachrichtigungen erhalten, während die App im Hintergrund ist? Vielen Dank
Anscheinend müssen Sie (trotz der Methode swizzling, die dies automatisch tun sollte) das APNS-Token auf der Firebase-Instanz festlegen. Folglich müssen Sie die Methode didRegisterForRemoteNOtificationsWithDeviceToken
auch mit etwas implementieren
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
// set firebase apns token
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
}
Als zusätzliche Anmerkung. Die Verwendung von "priority":"high"
war für Tests hilfreich, da die Benachrichtigung sofort gesendet wurde.
Befolgen Sie diese Schritte, nachdem Sie ein erfolgreiches Token von FCM erhalten haben, um den Abruf der Hintergrundnutzdaten mithilfe von FCM zu aktivieren:
Öffnen Sie Project Navigator> AppCapabilities> Hintergrundmodi> Suchen Sie nach Remote-Benachrichtigungen
In App.delegate definieren Sie:
func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print("userinfo in background mode on-\(userInfo)")
completionHandler(UIBackgroundFetchResult.newData)
}
Formatieren Sie Ihre Nutzdaten korrekt gemäß den Apple-Richtlinien: Geben Sie die Linkbeschreibung hier ein
Vergessen Sie nicht, das Schlüsselwertpaar hinzuzufügen: {"content-available":1}
, Es sei denn, Sie können keine Nutzdaten im Hintergrund abrufen.
versuchen Sie jetzt, die Benachrichtigung erneut mit dem FCM-Token zu senden. Hab eine glückliche Kodierung
Stellen Sie sicher, dass Sie "content_available": true in der JSON-Payload hinzugefügt haben. Andernfalls erhalten Sie keine Push-Benachrichtigung im Hintergrundmodus.
"notification" : {
"content_available" : true,
"body" : "this is body",
"title" : "this is title"
}
Ähnlich wie bei Daniel Georges Lösung könnte ich mein Problem beheben mit:
Messaging.messaging().apnsToken = deviceToken
FirebaseInstanceID 2.0.8, FirebaseMessaging 2.0.8
Das gewünschte Verhalten, zumindest für meine App, gilt für das Eintreffen einer Push-Benachrichtigung, bei der der Inhalt der PN (Push-Benachrichtigung) auf einer gewünschten Seite in der App angezeigt werden soll.
Ich habe drei verschiedene App-Zustände, in denen ein PN ankommen kann: .__ (natürlich hängt es von Ihrer Implementierung ab, aber Sie sollten eine Vorstellung davon bekommen, wie Apple das PN in diesen Zuständen verarbeitet).
(das Verhalten wird von Apple bestimmt!)
1) Die App steht im Vordergrund:
In diesem Fall verarbeitet die App Always / die PN
2) Die App befindet sich im Hintergrund:
In diesem Fall verarbeitet die App Always / die PN
3) Die App wird beendet/geschlossen:
jetzt gibt es drei möglichkeiten
wischbenachrichtigung weg -> PN wird von der AppNICHTverarbeitet
Öffnen Sie die App über das Startsymbol direkt -> PN wirdNICHTvon der App verarbeitet
klicken Sie auf die Benachrichtigung -> PN wird von der App verarbeitet
Dies hängt natürlich von Ihrer Implementierung ab, denn für den Fall "3. Öffnen Sie die App direkt über das Startsymbol" können Sie einfach alle PN auf dem App-Start über eine zusätzliche API abrufen. ABER Sie sollten wissen, wie Apple die PN-Verarbeitung in einigen Fällen verhindert.
Ich hoffe das hilft jemandem!