web-dev-qa-db-fra.com

Les notifications Silent Push ne sont délivrées que si l'appareil est en charge et / ou que l'application est au premier plan

J'ai implémenté des notifications Push silencieuses mais j'ai remarqué un comportement étrange. Les notifications Push silencieuses sont gérées via:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

Les messages Push silencieux ne semblent être reçus que si l'appareil est en charge (c'est-à-dire un câble connecté) et/ou si mon application est au premier plan.

Si je déconnecte l'appareil du chargeur (ou Mac), les notifications Push silencieuses ne sont plus reçues sauf l'application est au premier plan.

Je reçois des notifications Push non silencieuses normalement dans les deux cas.

Si je rebranche le câble USB, j'obtiens le comportement attendu et des notifications Push silencieuses sont reçues, que l'application soit au premier plan ou en arrière-plan.

J'utilise UILocalNotification donc je sais ce qui est reçu.

Le fait que tout fonctionne bien avec l'appareil connecté suggère que mes notifications push silencieuses sont correctement configurées et que l'application a les bons modes d'arrière-plan définis dans la liste, etc.

Ce comportement est reproductible sur iPhone 5s, 6 et iPad 2 fonctionnant tous soit IOS 8 ou 8.1.

Quelqu'un d'autre a-t-il vécu cela? Il doit être facile à reproduire. Pourquoi le simple fait de brancher un appareil sur un chargeur devrait-il changer la capacité de recevoir des notifications Push silencieuses?

54
user1024447

Nous avons connu le même comportement et essayons de comprendre pourquoi iOS décide de délivrer certaines notifications et pas d'autres.

Ce que nous avons élaboré jusqu'à présent, c'est:

  • Les messages seront reçus de manière plus fiable en arrière-plan lorsqu'ils sont sur wifi puis sur des données cellulaires. En fait, lorsque vous êtes sur un réseau cellulaire (3g/4g), si la force de votre signal n'est pas assez forte, iOS reçoit le message Push, mais ne réveillera pas votre application. Nous avons posté sur les forums Apple Apple à ce sujet ici: https://devforums.Apple.com/message/1069814#1069814 . Nous avons également ouvert un ticket d'assistance, et l'équipe de support nous a dit de le déposer en tant que rapport de bug, ce que nous avons fait il y a quelques semaines et attendons toujours de recevoir des nouvelles.

  • Lorsque vous recevez un message Push, vous devez appeler le fetchCompletionHandler dès que possible. Techniquement, vous disposez de 30 secondes pour effectuer le traitement en arrière-plan, mais iOS a mis en place une formule selon laquelle plus vous envoyez des messages Push fréquemment et en fonction du temps que vous passez à traiter ces messages avant de remettre l'application en état suspendu, iOS peut réduire le montant de fois votre application se réveillera à l'avenir.

Voir ici de Apple didReceiveRemoteNotification: fetchCompletionHandler: documentation:

Dès que vous avez fini de traiter la notification, vous devez appeler le bloc dans le paramètre du gestionnaire ou votre application sera fermée. Votre application a jusqu'à 30 secondes de temps d'horloge murale pour traiter la notification et appeler le bloc du gestionnaire d'achèvement spécifié. En pratique, vous devez appeler le bloc gestionnaire dès que vous avez terminé de traiter la notification. Le système suit le temps écoulé, la consommation d'énergie et les coûts de données pour les téléchargements en arrière-plan de votre application. Les applications qui consomment beaucoup d'énergie lors du traitement des notifications Push ne sont pas toujours réveillées tôt pour traiter les futures notifications.

Lors de nos tests, nous avons fréquemment envoyé des notifications Push silencieuses à notre application (toutes les 10 à 30 secondes). Et l'application est réveillée pendant environ 3 secondes avant de la remettre en veille. Nous avons certainement remarqué au fil du temps une dégradation de la fréquence à laquelle notre application se réveille au point où iOS ne la réveillera que toutes les 15 à 30 minutes. Il semble donc y avoir une sorte de formule de désintégration/limitation en place, mais nous ne pouvons trouver aucune documentation sur la façon dont cela fonctionne exactement. Nous avons demandé cette formule et les variables de Apple comme demande de support, mais ils ont dit "Les informations que vous demandez ne sont pas accessibles au public" et nous ont à nouveau demandé de déposer un rapport de bogue.

Donc, j'espère que cela est utile? Nous essayons toujours d'en savoir plus nous-mêmes, c'est pourquoi j'ai trouvé cette question :)

60
Kevin D.

Avec l'arrière-plan iOS8, la livraison push aux applications a changé. Un Push en arrière-plan ne sera désormais fourni à l'application que dans certaines circonstances. Apple n'a pas indiqué explicitement quelles sont exactement ces circonstances, mais d'après mon expérimentation approfondie, il s'agit essentiellement de savoir si le téléphone est en charge ou non. Il y a d'autres variables en jeu (telles que le type de réseau , type d'appareil, Wi-Fi activé), mais le principal facteur majeur est de savoir si l'appareil est en charge ou non à l'arrivée du Push.

Si le téléphone est chargé via une alimentation secteur directe ou indirectement en étant connecté par USB à un ordinateur, les poussées d'arrière-plan seront livrées à l'application la grande majorité du temps. Mais déconnectez le téléphone de l'alimentation ou de l'USB et le Push en arrière-plan ne sera presque jamais livré à l'application, même si la batterie du téléphone est chargée à 100%.

Vous pouvez très facilement tester cela par vous-même en envoyant quelques pressions pendant que le téléphone est en charge par rapport à ce qu'il n'est pas. MAIS vous devez tenir compte du fait que les push d'arrière-plan avec une build de développement et en utilisant l'environnement sandbox NE se comportent PAS de la même manière que les push d'arrière-plan avec une build de production et un environnement de production, les push d'arrière-plan sont en fait plus susceptibles d'être livrés à l'application en développement puis ils sont en production, il est donc essentiel de tester en utilisant une version de production et l'environnement de production d'Apple pour voir les résultats réels.

Notez qu'il y a deux étapes pour la livraison Push, la première est qu'elle doit être livrée au téléphone lui-même, la seconde est une fois que le téléphone l'a, elle doit ensuite être livrée par le système d'exploitation à l'application. Dans iOS7, des choses telles que le turing sur le Wifi augmentaient les chances que le Push arrive sur le téléphone. Cependant, avec iOS8, même si le Push est livré avec succès au téléphone, le système d'exploitation ne le transfère pas vers une application d'arrière-plan si le téléphone n'est pas chargé. Cela signifie que le téléphone reçoit la notification et la conserve, parfois pendant plusieurs heures, avant de pouvoir la transmettre à l'application si le téléphone n'est pas chargé.

9
Gruntcakes

J'ai rencontré le même problème et la raison pour laquelle je ne reçois pas de notification Push pendant que l'application ne se charge pas est que lorsque le mode faible consommation est activé à partir de Settings > Battery il désactive background-fetch fonction pour toutes les applications.

Ce qui empêche l'appareil de recevoir une notification Push.

Ce lien pourrait être utile. Documentation Apple

8
Manan Devani

J'ai également remarqué la même chose et perdu du temps à comprendre. Voir https://stackoverflow.com/a/31237889/172476

Si vous avez désactivé Bg App Refresh, Push silencieux à distance sera abandonné silencieusement (l'ironie).

Cependant, mon observation est que si vous vous connectez à Xcode via un câble, le paramètre Bg App Refresh est ignoré et tout Push silencieux pour votre application fonctionne.

Je soupçonne fortement qu'il s'agit d'une fonctionnalité non documentée: la charge entraîne l'ignorance du paramètre Bg App Refresh.

5
Mave

Cela ne fonctionne pas car vous avez activé le mauvais mode d'arrière-plan dans le plist. Vous devez activer le remote-notification tag (l'application télécharge du contenu en réponse aux notifications Push), pas à récupérer. La récupération est utilisée pour autre chose. Vous devrez peut-être également utiliser la clé de contenu disponible dans votre charge utile JSON, par exemple,

{
   "aps": {
      "content-available": 1
    },
    "yourdatakey":{data}
}
2
jrlocke

J'espère que vous utilisez APNS fournissant la priorité en tant que "CONSERVE_POWER" (5), essayez de la changer en "IMMEDIATE" (10)

1
Mohamed yaseen

SI VOTRE APP IS PAS DE VOIP VOUS NE POUVEZ PAS SUIVRE CETTE RÉPONSE [votre application sera rejetée]

J'ai trouvé une autre solution qui a fonctionné pour moi en utilisant PushKit Framework

Les push VoIP fournissent des fonctionnalités supplémentaires en plus du Push standard requis pour les applications VoIP pour effectuer le traitement à la demande du Push avant d'afficher une notification à l'utilisateur

Lorsque j'envoie VOIP Push, l'application se réveille quel que soit l'état de l'application et peut effectuer toutes les opérations

S'inscrire à VOIP PushNotification dans didFinishLaunchingWithOptions

 PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
pushRegistry.delegate = self;
pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];


- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{
if([credentials.token length] == 0) {
    NSLog(@"voip token NULL");
    return;
}

NSString *originalToken=[NSString stringWithFormat:@"%@",credentials.token];
NSString *token = [originalToken stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"PushCredentials: %@",token);}

alors vous pouvez gérer n'importe quelle extraction en arrière-plan dans cette fonction une fois que vous avez reçu la notification push VOIP

-(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type

REMARQUE: vous devez utiliser un certificat qui active le certificat de services VoIP

enter image description here

0
khaled

Je rencontre ce problème depuis un certain temps, et je suis très reconnaissant pour cette question et @Kevin D. partageant leur compréhension. Je commence à penser que https://stackoverflow.com/a/30834566/1449799 et https://developer.Apple.com/library/ios/documentation/NetworkingInternet/ Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html # // Apple_ref/doc/uid/TP40008194-CH101-SW4 (voir priority dans l'un des tableaux) explique pourquoi mon application rencontre des problèmes:

C'est une erreur d'utiliser cette priorité pour un Push qui contient uniquement le content-available clé.

Pour envoyer les notifications, j'utilise node-apn où la valeur par défaut (dont j'ai également besoin) est de définir la priorité sur max (10 [attention, il ne semble que 10 et 5 sont des valeurs correctes pour le moment]), mais comme je voulais une notification silencieuse , je n'ai pas alert, badge ou sound set.

0
Michael