web-dev-qa-db-fra.com

Appuis silencieux non livrés à l'application sur iOS 11

J'ai remarqué que sur iOS 11 beta 2, les notifications silencieuses ne sont pas transmises au application:didReceiveRemoteNotification:fetchCompletionHandler, quel que soit l'état de l'application (arrière-plan/avant-plan).

J'ai implémenté la méthode UIApplicationDelegeteapplication:didReceiveRemoteNotification:fetchCompletionHandler et j'envoie le push en mode silencieux suivant

{  
  "aps": {  
    "content-available": 1  
  },  
  "mydata": {  
    "foo": "bar"  
  }  
} 

mais la méthode déléguée n'est pas appelée sur iOS 11. 

Cela fonctionne bien sur d'autres versions d'iOS et la section de documentation Configuration d'une notification silencieuse ne mentionne pas qu'il faille faire autre chose.

Est-ce un bug dans iOS 11 ou ai-je oublié quelque chose de nouveau dans iOS 11? 

Veuillez noter que je ne parle ni n'utilise le framework UserNotification qui ne devrait pas être nécessaire pour envoyer des push silencieux.

Voici un exemple de projet qui illustre le problème (vous devrez définir votre propre identifiant de paquet)

Lorsque vous définissez l'exemple de projet et envoyez une charge ci-dessus à l'application, vous pouvez utiliser la console macOS pour vérifier que la diffusion est correctement envoyée à l'appareil, mais pas à l'application.

MISE À JOUR 10.08

Il semble que le comportement est aléatoire. Parfois, après le redémarrage de l'appareil, la charge utile est livrée correctement mais cesse de fonctionner après un certain temps.

Comme vous pouvez le voir sur la capture d'écran suivante, le Push marqué 1 est uniquement fourni à l'appareil et le Push 2 (après le redémarrage de l'appareil) est également transmis à l'application.

enter image description here

MISE À JOUR 14.08 - iOS 11 Bêta 6

Toujours le même comportement. Une autre chose qui est censée fonctionner mais ne fonctionne pas est la suivante. Lorsque le schéma de l'application est défini sur "Attendre que le fichier exécutable soit lancé", un Push en mode silencieux est censé réveiller l'application et la démarrer en arrière-plan. 

enter image description here

MISE À JOUR 21.08 - iOS 11 Bêta 7

Toujours le même comportement et pas les mises à jour d'Apple dans le rapport de bogue.

MISE À JOUR 29.08 - iOS 11 Bêta 8

Toujours le même problème. Les étapes pour reproduire que j'utilise maintenant sont les suivantes:

  • Dans le schéma de projet Xcode, sélectionnez "Attendre que le fichier exécutable soit lancé".
  • Ajouter un point d'arrêt dans le didReceiveRemoteNotification: fetchCompletionHandler
  • Démarrer l'application sur l'appareil
  • Envoyer le Push silencieux ci-dessus

Expected: l'application est passée de l'état suspendu à l'arrière-plan et le didReceiveRemoteNotification: fetchCompletionHandler est appelé.

Actual: rien ne se passe 

MISE À JOUR 06.09 - iOS 11 Beta 10

J'ai toujours le même comportement de buggy. Le ticket d’Apple a été mis à jour avec la réponse suivante:

Apple Developer Relations 6 septembre 2017, 10:42 PM L'ingénierie a a fourni les commentaires suivants sur ce problème: 

Nous avons pu exécuter l'exemple d'application et tester le comportement. Nous Nous n’avons vu aucun problème lorsque nous avons testé ceci comme décrit. 

Les pushs ne sont pas garantis pour arriver à l'application quand elle est en marche l'arrière-plan, et les journaux ici indiquent que nous ne croyons pas que l'application est être utilisé assez pour le lancer. 

Nous nous voyons faire des poussées de temps en temps lorsque les conditions sont réunies bien. 

Nous croyons que cela se comporte correctement.

Mise à jour 11.09

Mon rapport de bogue Apple a été fermé et marqué comme duplicata de 33278611 qui reste ouvert

MISE À JOUR 13.09 - iOS 11 GM

Grâce aux commentaires de kam800 (voir ci-dessous), j'ai effectué d'autres tests et formulé ces observations:

Il semble y avoir un nouveau démon dans iOS 11 dasd DuetActivitySchedulerDaemon qui supprime complètement les données Push ou retarde la livraison des données:

Livraison reportée

Journaux de la console

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

Problèmes de livraison reportés

  • Lorsque la livraison des données Push est reportée et que l'application est lancée, la livraison des données n'est transmise que lorsque la date de livraison est atteinte, ce qui peut être plusieurs minutes à l'avenir. Cela va complètement à l'encontre de l'utilisation des transmissions de données pour garder le contenu de la nouvelle application prêt pour le prochain lancement. Je cite ici encore une fois la documentation d'Apple: 

"Les notifications silencieuses améliorent l'expérience utilisateur en vous aidant à maintenir Votre application à jour, même lorsqu'elle n'est pas en cours d'exécution."

  • Lorsque deux poussées de données sont envoyées vers une application suspendue, elles sont reportées par iOS 11 au lieu de réactiver directement l'application. Lorsque l'heure de livraison est atteinte, seul le dernier data Push est livré! Les push précédents sont perdus et ne sont pas livrés via la méthode du délégué, ce qui entraîne une perte de données.

Livraison annulée

Journaux de la console

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

Problèmes de livraison annulés

Dans ce cas, les données Push sont complètement perdues et ne sont jamais livrées sur iOS 11 alors qu'elles ont été correctement livrées sur iOS 10.

MISE À JOUR 19.09 - iOS 11 GM

J'ai également remarqué que lorsque l'application est au premier plan et que la notification n'est pas transmise à l'application, les journaux suivants apparaissent dans la console:

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
147
Jan

Donc, les notes de publication de iOS 11.1 beta 1 disent

iOS 11.1 beta 1 vient de sortir et ils mentionnent: "Notifications Problèmes résolus • Les notifications Push silencieuses sont traitées plus fréquemment. (33278611) 

J'ai fait quelques tests et il semble en effet être corrigé: 

Etat suspendu

Lorsque je lance l'application en mode suspendu et que j'envoie une Push silencieuse, l'application est ramenée à l'arrière-plan et le délégué didReceiveRemoteNotification:fetchCompletionHandler est appelé.

Etat de premier plan

De la même manière, lorsque l'application est au premier plan et qu'un Push en mode silencieux est envoyé, le délégué semble être appelé comme prévu. C'était au hasard pas fonctionnait dans les versions précédentes d'iOS 11, je vais donc le confirmer après plus de tests.

28
Jan

Je voulais juste ajouter mes 2 centimes ici car je suis touché par ce problème aussi et j'ai remarqué qu'Apple a fermé plusieurs radars sur ce problème en disant qu'ils ne pouvaient pas se reproduire. Une chose intéressante que j'ai trouvée est que les push seront livrés si l'application est en arrière-plan pendant qu'elle est attachée au débogueur.

Si je tue le débogueur, débranche mon téléphone, lance l'application et envoie la charge Push silencieuse, l'application ne se réveille PAS. Le journal de la console indique que le système annule la livraison de la charge utile à mon application.

J'ai soumis un radar avec un petit exemple d'application reproduisant le problème. J'ai aussi explicitement noté dans le radar que la personne travaillant sur mon ticket ne devait pas exécuter l'application attachée au débogueur pour reproduire le problème. Voici le lien: https://bugreport.Apple.com/web/?problemID=34461063

Espérons que cela entraînera des progrès sur cette question.

16
Bill Dunay

Ressemble à un nouveau comportement d'iOS 11. iOS 11 bêta 10 fournit quelques journaux descriptifs concernant ce problème:

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

Il semble que chaque push silencieux est livré à iOS, mais le démon dasd utilise plusieurs stratégies pour décider si le push silencieux doit être livré à l'application (par exemple, au niveau de la batterie). J'ai réussi à recevoir une Push silencieuse hier soir, mais mon iPhone était alors connecté au chargeur - le score BatteryLevelPolicy était probablement suffisamment élevé pour recevoir cette Push silencieuse.

Apple ne donne aucune information officielle sur ce comportement côté iOS, il n'y a que des informations sur la limitation côté serveur:

Les notifications silencieuses ne constituent pas un moyen de garder votre application éveillée l'arrière-plan, ils ne sont pas non plus destinés aux mises à jour hautement prioritaires. APNs traite les notifications en mode silencieux comme ayant une priorité basse et peut limiter leur livraison si le nombre total devient excessif. L'actuel les limites sont dynamiques et peuvent changer en fonction des conditions, mais essayez de ne pas.. envoyer plus de quelques notifications par heure.

Je garde les doigts croisés, ils ont changé ce comportement, car cela corrigera mon application :) D'un autre côté, ce changement est positif - une des nombreuses choses permettant à la batterie d'un iPhone de durer plus longtemps que les téléphones Android.

11
kam800

les notes de version bêta d'iOS 11.1 incluent: Notifications Problèmes résolus Les notifications Push silencieuses sont traitées plus fréquemment. (33278611)

7
Andrew Gould

Apple Developer Relations vient d'ajouter un commentaire à mon radar:

Nous pensons que ce problème est résolu dans la dernière version bêta d'iOS 11.2.

Veuillez tester avec la dernière version bêta d'iOS. Si vous avez toujours des problèmes, s'il vous plaît mettez à jour votre rapport de bogue avec tous les journaux ou informations pertinents qui pourrait nous aider à enquêter.

https://developer.Apple.com/download/

en train d'installer iOS 11.2 bêta - testera le comportement Push silencieux

6
Thomas Einwaller

iOS 11.1 Beta 2 contient également

Notifications
Resolved Issues
• Silent Push notifications are processed more frequently. (33278611)

dans Notes de mise à jour - va le tester maintenant.

MISE À JOUR - 11.10.2017 - iOS 11.1 Bêta 2

Après avoir utilisé notre application pendant 2 jours dans des "scénarios du monde réel", il semble y avoir une réelle amélioration dans cette version d'iOS. Je commence prudemment à croire que cela est réglé.

5
Thomas Einwaller

iOS 11.4.1, Swift 4

J'avais des problèmes avec des push silencieux qui n'arrivaient pas (de CloudKit) et j'ai essayé tout ce que tout le monde a mentionné ici. Ensuite, j'ai décidé d'essayer de définir une alertBody vierge sur mes objets CKNotificationInfo() comme ceci:

let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
info.alertBody = ""

Cela a rendu les envois envoyés avec une priorité plus élevée (mais ils étaient toujours des envois silencieux) et je n'ai plus eu l'erreur dans mes journaux de périphérique que le Push était ignoré.

J'espère que cela aide quelqu'un. :)

3
Clifton Labrum

En guise de solution de contournement, nous ajoutons une clé "notification" et un "titre" avec une chaîne vide en tant que valeur . Ceci réveille le rappel didReceive dans appDelegate.

2
elkorb

J'avais un problème similaire avec mon application, jusqu'à ce que iOS 10 reçoive les notifications Push et que application:didReceiveRemoteNotification:fetchCompletionHandler soit appelé correctement. Mais lors de la mise à jour vers iOS 11, les notifications Push cessaient de fonctionner.

Le problème avec mon code était, même si j'utilisais content-available: 1 et mutable-content: 1 dans le contenu de la notification Push, l'option de recherche en arrière-plan n'était pas activée. Mais cela fonctionnait parfaitement jusqu'à iOS 10. 

 Make sure you turned ON both these capabilities.

Après avoir activé la fonction de recherche en arrière-plan, cela fonctionne maintenant.

2
Sudeep george

Au moment de rédiger cette réponse, je suis confronté exactement au même problème que Bill Dunay's answer.

Mon exigence était de recevoir des notifications en mode silencieux lorsque l'application est au premier plan et rien lorsque l'application est en arrière-plan/en cours d'exécution. Et ma solution était la suivante. Je n'utilise pas de badges, donc la mise à zéro n'est pas un problème pour moi.

{
    "aps" : {
        "badge" : 0,
        "sound" : ""
    },
    "mydata": {  
        "foo": "bar"  
    }  
}

Veuillez noter que je n'utilise pas délibérément "contenu disponible". Paramètre qui entraîne la logique d'optimisation iOS pour retarder/annuler la remise de la notification.

1
Rammohan Raja

Il s’agit donc bien d’un bogue dans iOS 11 qui est maintenant corrigé dans iOS 11 bêta 3. Le application:didReceiveRemoteNotification:fetchCompletionHandler est maintenant appelé correctement lorsqu’un Push silencieux est reçu à la fois au premier plan ou en arrière-plan.

METTRE &AGRAVE; JOUR

Non, ce n'est pas corrigé et cela se produit encore dans iOS beta 3 et 4

1
Jan

Je reçois le même problème pour certaines notifications (pas nécessairement silencieux).

Après avoir examiné toutes les mises à jour et réponses, je peux ajouter deux mises à jour qui peuvent aider:

  • J'ai constaté que l'accès à la méthode UIApplication.shared.isRegisteredForRemoteNotifications lors de la réception d'une notification entraînait le blocage de l'application sans rien signaler à Xcode. Vérifiez si vous exécutez du code après avoir reçu la notification qui accède à la méthode. ( isRegisteredForRemoteNotifications verrouillant l’UI avec semaphore_wait_trap ).

    • J'ai découvert une erreur d'analyse de notification Push sur la console car le "title-loc-args" : [3333] n'acceptait pas 3333 littéralement mais l'acceptait comme une chaîne "title-loc-args" : ["3333"]. Cela a rendu mon blocage complet de l'interface après avoir accédé à la méthode ci-dessus, uniquement sur iOS 11, cela fonctionne sur iOS 12.
  • J'ai aussi découvert que, avec exactement le même code, cela fonctionne sans problème sur iOS 12.0 (16A5366a). Mais sur iOS 11, cela se passe.

1
Rageofflames

Dans mon cas, les notifications silencieuses étaient utilisées pour mettre à jour l'interface utilisateur une fois le travail effectué sur le site du serveur; il était donc pénible d'avoir un contenu non pertinent dans l'application. Parce que notre charge utile de notification silencieuse contient même le titre et le corps, j'implémente ces méthodes pour que les notifications de travail soient actives dans l'application active/inactive, sans charge et avec l'actualisation de l'application en arrière-plan désactivée et même dans l'état Alimentation faible.

Pour que cela fonctionne, j'ajoute délégué et crée une extension avec le protocole UNUserNotificationCenterDelegate et la méthode willPresent notification (iOS 10+), déclenchée à chaque fois avec une charge utile correcte. Pour ne pas afficher la notification lorsque l'application est active, complétez simplement l'appel avec un badge ou un son ..___ Je me suis retrouvé avec quelque chose comme ceci

    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)
        }
    }
}

Et pour que ces états fonctionnent lorsque l’application est en arrière-plan et que la notification est silencieuse, n’appelez pas mes méthodes. Je reçois des notifications directement du centre de notification dans applicationDidBecomeActive par:

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`
                    }
                })
            }
        }
0
Andrew H