Ich habe festgestellt, dass unter iOS 11 Beta 2 die stillen Benachrichtigungen unabhängig vom Status der App (Hintergrund/Vordergrund) nicht an application:didReceiveRemoteNotification:fetchCompletionHandler
übermittelt werden.
Ich habe die UIApplicationDelegete
-Methode application:didReceiveRemoteNotification:fetchCompletionHandler
implementiert und sende den folgenden stillen Push
{
"aps": {
"content-available": 1
},
"mydata": {
"foo": "bar"
}
}
die Delegate-Methode wird jedoch unter iOS 11 nicht aufgerufen.
Es funktioniert gut mit anderen Versionen von iOS und dem Dokumentationsabschnitt Konfigurieren einer unbeaufsichtigten Benachrichtigung erwähnt nicht, dass etwas anderes getan werden sollte.
Ist das ein Fehler in iOS 11 oder habe ich etwas Neues in iOS 11 vermisst?
Bitte beachten Sie, dass ich nicht über das UserNotification
-Framework spreche oder es verwende, das nicht für das Senden von Silent Pushs benötigt wird.
Hier ist ein Beispielprojekt , das das Problem veranschaulicht (Sie müssen Ihre eigene Bundle-ID festlegen)
Wenn Sie das Beispielprojekt zu Mittag essen und eine obige Nutzlast an die App senden, können Sie mit der macOS-Konsole feststellen, dass der Push ordnungsgemäß an das Gerät übermittelt wird, nicht jedoch an die App.
Es scheint, dass das Verhalten zufällig ist. Nach dem Neustart des Geräts wird die Nutzlast manchmal korrekt geliefert, funktioniert aber nach einiger Zeit nicht mehr.
Wie Sie auf dem folgenden Screenshot sehen können, wird der als 1 markierte Push nur an das Gerät geliefert, und Push 2 (nach Neustart des Geräts) wird ebenfalls an die App übermittelt.
Immer noch dasselbe Verhalten. Eine andere Sache, die funktionieren sollte, aber nicht funktioniert, ist die folgende. Wenn das Anwendungsschema auf "Warten auf das Starten der ausführbaren Datei" eingestellt ist, soll ein stilles Push die Anwendung aufwecken und im Hintergrund starten.
Immer noch das gleiche Verhalten und keine Updates von Apple im Fehlerbericht.
Immer noch dasselbe Problem. Die zu reproduzierenden Schritte, die ich jetzt verwende, sind folgende:
didReceiveRemoteNotification: fetchCompletionHandler
hinzu.Expected: Die App wird aus dem angehaltenen Status in den Hintergrund versetzt und der didReceiveRemoteNotification: fetchCompletionHandler
wird aufgerufen
Actual: nichts passiert
Ich habe immer noch das gleiche fehlerhafte Verhalten. Das Ticket von Apple wurde mit der folgenden Antwort aktualisiert:
Apple Developer Relations 6. September 2017, 10:42 PM Das Engineering hat hat folgendes Feedback zu diesem Problem gegeben:
Wir konnten die Beispiel-App zum Laufen bringen und das Verhalten testen. Wir haben keine Probleme festgestellt, als wir dies wie beschrieben getestet haben.
Es ist nicht garantiert, dass Pushs in der App ankommen, wenn sie in .__ ausgeführt wird. der Hintergrund und die Protokolle hier zeigen an, dass wir nicht glauben, dass die App .__ ist. genug verwendet, um es zu starten.
Wir sehen, dass wir von Zeit zu Zeit Pushs liefern, wenn die Bedingungen erfüllt sind gut.
Wir glauben, dass sich dies richtig verhält.
Mein Apple-Fehlerbericht wurde geschlossen und als Duplikat von 33278611
markiert, der weiterhin geöffnet ist
Dank der Kommentare von kam800 (siehe unten) habe ich mehr getestet und habe folgende Beobachtungen gemacht:
In iOS 11 scheint es einen neuen Daemon zu geben, dasd DuetActivitySchedulerDaemon
, der die Daten entweder vollständig verwirft oder die Datenübertragung verzögert:
Konsolenprotokolle
default 13:11:47.177547 +0200 dasd DuetActivitySchedulerDaemon CANCELED: com.Apple.pushLaunch.net.tequilaapps.daylight:C03A65 <private>! lifecycle com.Apple.duetactivityscheduler
default 13:11:47.178186 +0200 dasd DuetActivitySchedulerDaemon Removing a launch request for application <private> by activity <private> default com.Apple.duetactivityscheduler
default 12:49:04.426256 +0200 dasd DuetActivitySchedulerDaemon Advancing start date for <private> by 6.5 minutes to Wed Sep 13 12:55:31 2017 default com.Apple.duetactivityscheduler
default 13:21:40.593012 +0200 dasd DuetActivitySchedulerDaemon Activity <private>: Optimal Score 0.6144 at <private> (Valid Until: <private>) scoring com.Apple.duetactivityscheduler
default 13:21:40.594528 +0200 dasd DuetActivitySchedulerDaemon Setting timer (isWaking=1, activityRequiresWaking=0) between <private> and <private> for <private> default com.Apple.duetactivityscheduler
Verschobene Lieferprobleme
"Stille Benachrichtigungen verbessern die Benutzererfahrung, indem sie Ihnen helfen, Ihre App auf dem neuesten Stand zu halten, selbst wenn sie nicht läuft."
Konsolenprotokolle
default 13:35:05.347078 +0200 dasd DuetActivitySchedulerDaemon com.Apple.pushLaunch.net.tequilaapps.daylight:C03A65:[
{name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Must Not Proceed, Score: 0.00}}
], FinalDecision: Must Not Proceed} scoring com.Apple.duetactivityscheduler
Abgebrochene Zustellungen
In diesem Fall ist der Daten-Push vollständig verloren und wurde unter iOS 11 nie bereitgestellt, während er korrekt unter iOS 10 bereitgestellt wurde.
Ich habe auch bemerkt, dass wenn die Anwendung im Vordergrund ist und die Benachrichtigung nicht an die App übermittelt wird, die folgenden Protokolle in der Konsole angezeigt werden:
default 08:28:49.354824 +0200 apsd apsd <private>: Received message for enabled topic '<private>' onInterface: NonCellular with payload '<private>' with priority 10 for device token: NO courier-oversized com.Apple.apsd
fault 08:33:18.128209 +0200 dasd Foundation <NSXPCConnection: 0x151eee460> connection from pid 55: Exception caught during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: value for key 'NS.objects' was of unexpected class 'NSNull'. Allowed classes are '{(
NSArray,
NSData,
NSString,
NSNumber,
NSDictionary,
NSUUID,
_DASActivity,
NSSet,
_DASFileProtection,
NSDate,
NWParameters,
NWEndpoint
)}'. general com.Apple.foundation.xpc
So sagen die Release Notes von iOS 11.1 Beta 1
iOS 11.1 Beta 1 wurde gerade veröffentlicht und sie erwähnen: "Benachrichtigungen Behobene Probleme • Silent Push-Benachrichtigungen werden häufiger verarbeitet. (33278611)
Ich habe ein paar Tests gemacht und es scheint tatsächlich behoben zu sein:
Wenn ich die App im angehaltenen Modus starte und einen stillen Push schicke, wird die App in den Hintergrund zurückgebracht und der didReceiveRemoteNotification:fetchCompletionHandler
-Delegat wird aufgerufen.
Wenn sich die Anwendung im Vordergrund befindet und ein stilles Push gesendet wird, scheint der Delegat wie erwartet aufgerufen zu werden. In früheren Versionen von iOS 11 funktionierte dies zufällig nicht , daher werde ich dies nach mehr Tests bestätigen.
Ich wollte nur meine 2 Cents hier hinzufügen, da ich auch von diesem Problem betroffen war und ich bemerkt habe, dass Apple zu diesem Problem mehrere Radargeräte geschlossen hat, die besagen, dass sie sich nicht reproduzieren könnten. Eine interessante Sache, die ich gefunden habe, ist, dass die Pushs geliefert werden, wenn die App im Hintergrund ist, während sie an den Debugger angehängt ist.
Wenn ich den Debugger töte, entferne mein Telefon, starte die App und sende die stille Push-Nutzlast. Ich sehe, dass die App NICHT geweckt wird. Im Konsolenprotokoll wird angezeigt, dass das System die Zustellung der Nutzdaten an meine App abbricht.
Ich habe ein Radar mit einer kleinen Beispiel-App eingereicht, die das Problem reproduziert. Ich habe auch im Radar explizit darauf hingewiesen, dass die Person, die an meinem Ticket arbeitet, die an den Debugger angehängte App nicht ausführen darf, um das Problem zu reproduzieren. Hier ist der Link: https://bugreport.Apple.com/web/?problemID=34461063
Ich hoffe, dies wird zu einigen Fortschritten in dieser Frage führen.
Sieht aus wie ein neues Verhalten von iOS 11. iOS 11 Beta 10 enthält einige beschreibende Protokolle zu diesem Problem:
default 23:18:51.806011 +0200 dasd com.Apple.pushLaunch.com.acme.Acme:F7E7D0:[
{name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Can Proceed, Score: 0.50}}
{name: BatteryLevelPolicy, policyWeight: 1.000, response: {Decision: Can Proceed, Score: 0.87, Rationale: [{batteryLevel == 62}]}}
{name: DeviceActivityPolicy, policyWeight: 5.000, response: {Decision: Can Proceed, Score: 0.20}}
] sumScores:52.279483, denominator:81.410000, FinalDecision: Can Proceed FinalScore: 0.642175}
default 23:18:51.806386 +0200 dasd 'com.Apple.pushLaunch.com.acme.Acme:F7E7D0' has compatibility score of 1.000000 with 'com.Apple.CFNetwork-cc-111-79:E7272D'. Relaxing scores.
default 23:18:51.806855 +0200 dasd 'com.Apple.pushLaunch.com.acme.Acme:F7E7D0' CurrentScore: 0.642175, ThresholdScore: 0.738454 DecisionToRun:0
Es sieht aus, als würde jeder stille Push an das iOS übermittelt werden. Dasd-Daemon verwendet jedoch einige Richtlinien, um zu entscheiden, ob ein stummer Push für die App bereitgestellt werden soll (z. B. Akkuladestand). Ich habe gestern Nacht einen stillen Push erhalten, aber mein iPhone war zu dieser Zeit an ein Ladegerät angeschlossen. Wahrscheinlich war der BatteryLevelPolicy-Score hoch genug, um diesen einen stillen Push zu erhalten.
Apple gibt keine offiziellen Informationen zu diesem iOS-seitigen Verhalten an, es gibt nur Informationen zur serverseitigen Drosselung:
Stille Benachrichtigungen sind nicht dazu gedacht, Ihre App in .__ zu aktivieren. Der Hintergrund ist auch nicht für Updates mit hoher Priorität gedacht. APNs behandelt stille Benachrichtigungen als niedrige Priorität und kann deren .__ beeinträchtigen. Lieferung insgesamt, wenn die Gesamtzahl zu hoch wird. Die tatsächliche Die Grenzwerte sind dynamisch und können sich je nach Bedingungen ändern. Versuchen Sie jedoch nicht, Senden Sie mehr als ein paar Benachrichtigungen pro Stunde.
Ich drücke die Daumen, dass sie dieses Verhalten geändert haben, weil dies meine App reparieren würde. Andererseits ist diese Änderung gut - eines von vielen Dingen, die den iPhone-Akku länger halten als Android-Handys.
hinweise zur Betaversion von iOS 11.1 umfassen: Benachrichtigungen Behobene Probleme Silent Push-Benachrichtigungen werden häufiger verarbeitet. (33278611)
Apple Developer Relations hat gerade einen Kommentar zu meinem Radar hinzugefügt:
Wir glauben, dass dieses Problem in der aktuellen Beta von iOS 11.2 behoben wurde.
Bitte testen Sie mit der neuesten iOS-Beta. Wenn Sie immer noch Probleme haben, bitte Aktualisieren Sie Ihren Fehlerbericht mit allen relevanten Protokollen oder Informationen, die könnte uns bei der Untersuchung helfen.
derzeit wird die Betaversion von iOS 11.2 installiert - testet das stille Push-Verhalten
iOS 11.1 Beta 2 enthält auch
Notifications
Resolved Issues
• Silent Push notifications are processed more frequently. (33278611)
in den Versionshinweisen - testet es jetzt.
Nachdem Sie unsere App für 2 Tage in "realen Szenarien" verwendet haben, scheint sich in dieser Version von iOS eine echte Verbesserung zu ergeben. Ich beginne vorsichtig zu glauben, dass dies behoben ist.
iOS 11.4.1, Swift 4
Ich hatte Probleme mit Silent Pushes, die nicht ankamen (von CloudKit) und ich habe alles versucht, was alle hier erwähnt haben. Dann entschied ich mich zu versuchen, ein leeres alertBody
für meine CKNotificationInfo()
-Objekte wie folgt festzulegen:
let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
info.alertBody = ""
Dies hat dazu geführt, dass die Pushs mit einer höheren Priorität gesendet wurden (sie waren jedoch immer noch stille Pushes) und ich habe nicht mehr den Fehler in meinen Geräteprotokollen erhalten, dass der Push ignoriert wurde.
Ich hoffe das hilft jemandem. :)
Als Problemumgehung fügen wir einen "Benachrichtigungs" -Schlüssel und einen "Titel" mit leerem String als Wert hinzu .. _. Dies macht den didReceive-Rückruf in appDelegate aus.
Ich hatte ein ähnliches Problem mit meiner App, bis iOS 10 erhielt ich Push-Benachrichtigungen, und application:didReceiveRemoteNotification:fetchCompletionHandler
wurde korrekt aufgerufen. Aber bei einer Aktualisierung auf iOS 11 funktionierten Push-Benachrichtigungen nicht mehr.
Problem mit meinem Code war, obwohl ich content-available: 1 und mutable-content: 1 in Push-Benachrichtigungsnutzdaten verwendet habe. Die Hintergrundabruf-Option war nicht aktiviert. Aber es funktionierte bis iOS 10 einwandfrei.
Nachdem Sie die Hintergrundabruf-Funktion eingeschaltet haben, ist sie jetzt aktiv
Als ich diese Antwort schreibe, stehe ich vor genau demselben Problem wie Bill Dunays answer.
Meine Anforderung war, stille Benachrichtigungen zu erhalten, wenn sich die App im Vordergrund befindet und nichts, wenn sich die App im Hintergrund befindet/nicht ausgeführt wird. Und mein Workaround war das. Ich benutze keine Abzeichen, daher ist es für mich kein Thema, es auf Null zu setzen.
{
"aps" : {
"badge" : 0,
"sound" : ""
},
"mydata": {
"foo": "bar"
}
}
Bitte beachten Sie, dass ich bewusst nicht "content-available" verwende. Einstellung, die dazu führt, dass die iOS-Optimierungslogik die Zustellung der Benachrichtigung verzögert oder abbricht.
Dies ist in der Tat ein Fehler in iOS 11 und wurde nun in iOS 11 Beta 3 behoben. Der application:didReceiveRemoteNotification:fetchCompletionHandler
wird jetzt korrekt aufgerufen, wenn ein stiller Push sowohl im Vordergrund als auch im Hintergrund empfangen wird.
UPDATE
Nein, es ist nicht behoben und wird in iOS Beta 3 und 4 immer noch ausgeführt
Ich habe das gleiche Problem für einige Benachrichtigungen erhalten (nicht unbedingt stumm).
Nachdem ich alle Updates und Antworten durchgesehen habe, kann ich zwei Updates hinzufügen, die möglicherweise helfen:
Ich habe festgestellt, dass der Zugriff auf die UIApplication.shared.isRegisteredForRemoteNotifications
-Methode während des Empfangs einer Benachrichtigung dazu führt, dass die Anwendung angehalten wird, ohne etwas an Xcode zu melden. Überprüfen Sie, ob Sie Code ausführen, nachdem Sie die Benachrichtigung erhalten haben, dass auf die Methode zugegriffen wird. ( isRegisteredForRemoteNotifications sperrt die Benutzeroberfläche mit semaphore_wait_trap ).
"title-loc-args" : [3333]
3333 nicht wörtlich akzeptiert, sondern als Zeichenfolge "title-loc-args" : ["3333"]
. Dies führte dazu, dass mein gesamtes Interface zum Erliegen kam, nachdem ich auf die obige Methode zugegriffen habe. Nur unter iOS 11 funktioniert es unter iOS 12.Ich habe auch herausgefunden, dass es mit dem exakt gleichen Code unter iOS 12.0 (16A5366a) problemlos funktioniert. Aber auf iOS 11 passiert es.
In meinem Fall wurden unbeaufsichtigte Benachrichtigungen verwendet, um die Benutzeroberfläche zu aktualisieren, nachdem der Job auf dem Server ausgeführt wurde. Daher war es unangenehm, nicht relevante Inhalte in der App zu haben. Da unsere Nutzlast für die stille Benachrichtigung sogar Titel und Text enthält, implementiere ich diese Methoden, um funktionierende Benachrichtigungen in der aktiven/inaktiven App zu erhalten, nicht im Laden und bei deaktivierter Hintergrund-App-Aktualisierung und sogar im Energiesparmodus.
Damit dies funktioniert, füge ich Delegate hinzu und erstelle eine Erweiterung mit UNUserNotificationCenterDelegate
protocol und willPresent notification
(iOS 10+), die jedes Mal mit korrekter Nutzlast ausgelöst wird. Um die Benachrichtigung nicht anzuzeigen, wenn die App aktiv ist, rufen Sie einfach die Beendigung des Anrufs mit einem Ausweis oder einem Ton ab ... __
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
// MARK: - Lifecycle
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}
//this was only method to handle notifications before
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
//process silent notification
completionHandler(UIBackgroundFetchResult.newData)
}
}
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
//proces notification when app is active with `notification.request.content.userInfo`
if UIApplication.shared.applicationState == .active {
completionHandler(.badge)
}else {
completionHandler(.alert)
}
}
}
Um diese Zustände zu nutzen, wenn sich die App im Hintergrund befindet und die stille Benachrichtigung nicht meine Methoden aufrufen, erhalte ich Benachrichtigungen von der Benachrichtigungszentrale direkt in applicationDidBecomeActive
durch:
UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
debugLog(message: "unprocessed notification count: \(notifications.count)")
if notifications.count > 0 {
notifications.forEach({ (notification) in
DispatchQueue.main.async {
//handle `notification.request.content.userInfo`
}
})
}
}