Lorsque mon application est pas en cours d'exécution et reçoit une notification push, si je clique sur cette notification, l'application est lancée - mais alors il n'invite pas l'utilisateur avec la vue d'alerte que j'ai configurée, leur demandant s'ils veulent voir le contenu de la notification ou non. Il se lance juste et reste là.
Les notifications push fonctionnent parfaitement lorsque l'application est en cours d'exécution - en tant qu'application active ou en arrière-plan - mais rien ne fonctionne correctement lorsque l'application est pas fonctionnement.
J'ai essayé de me déconnecter du launchOptions
NSDictionary dans application: didFinishLaunchingWithOptions:
pour voir quelle charge son apport - mais il apparaît comme "(null)". Donc, il ne contient essentiellement rien - ce qui n'a pas de sens car ne devrait-il pas contenir la charge de la notification?
Quelqu'un a-t-il des idées sur la façon de faire fonctionner les notifications push à leur arrivée alors que l'application ne fonctionnait PAS?
EDIT: voici le code que j'utilise dans application: didReceiveRemoteNotification
juste pour voir ce qui est quoi:
if (UIApplicationStateBackground) {
NSLog(@"===========================");
NSLog(@"App was in BACKGROUND...");
}
else if (UIApplicationStateActive == TRUE) {
NSLog(@"===========================");
NSLog(@"App was ACTIVE");
}
else {
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 99];
UIAlertView *BOOM = [[UIAlertView alloc] initWithTitle:@"BOOM"
message:@"app was INACTIVE"
delegate:self
cancelButtonTitle:@"a-ha!"
otherButtonTitles:nil];
[BOOM show];
NSLog(@"App was NOT ACTIVE");
}
Donc, cela est censé prendre en charge tous les états de l'application - mais ce n'est pas le cas. Les notifications push ne fonctionnent que lorsque l'application est en cours d'exécution - en arrière-plan ou au premier plan ...
=================================================
UPDATE/EDIT # 2: selon la suggestion "@dianz" (ci-dessous), j'ai modifié le code de mon application: didFinishLaunchingWithOptions
pour inclure les éléments suivants:
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (localNotif) {
NSString *json = [localNotif valueForKey:@"data"];
UIAlertView *bam = [[UIAlertView alloc] initWithTitle:@"appDidFinishWithOptions"
message:json
delegate:self
cancelButtonTitle:@"cool"
otherButtonTitles:nil];
[bam show];
}
Cela fait apparaître la boîte AlertView, mais il ne semble pas y avoir de charge utile: le titre de AlertView apparaît ("appDidFinishWithOptions"), mais le json NSString apparaît VIDE ... Continuera à peaufiner ...
======================
EDIT # 3 - son fonctionne maintenant presque 100%
Donc, dans didFinishLaunchingWithOptions
:
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (localNotif) {
// Grab the pushKey:
pushKey = [localNotif valueForKey:@"pushKey"];
// "pushKey" is an NSString declared globally
// The "pushKey" in the "valueForKey" statement is part of my custom JSON Push Notification pay-load.
// The value of pushKey will always be a String, which will be the name of the
// screen I want the App to navigate to. So when a Notification arrives, I go
// through an IF statement and say "if pushKey='specials' then Push the
// specialsViewController on, etc.
// Here, I parse the "alert" portion of my JSON Push-Notification:
NSDictionary *tempDict = [localNotif valueForKey:@"aps"];
NSString *pushMessage = [tempDict valueForKey:@"alert"];
// Finally, ask user if they wanna see the Push Notification or Cancel it:
UIAlertView *bam = [[UIAlertView alloc] initWithTitle:@"(from appDidFinishWithOptions)"
message:pushMessage
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"View Info", nil];
[bam show];
}
J'implémente ensuite le alertView: clickedButtonAtIndex
méthode pour voir ce que l'utilisateur a choisi sur AlertView et procéder en conséquence.
Ceci, avec la logique didReceiveRemoteNotification
fonctionne parfaitement.
CEPENDANT ... lorsque l'application n'est PAS en cours d'exécution, et je lui envoie une notification push, si je ne clique pas sur l'alerte de notification push dès qu'elle arrive et attendez plutôt qu'elle disparaisse (ce qui se produit après comme 3- 4 secondes), et puis je clique sur l'icône de l'application - qui a maintenant un BADGE de 1 dessus - l'application démarre, mais je ne le fais pas obtenir l'alerte de notification push du tout lors de son lancement. Il se trouve juste là.
Je suppose que je dois comprendre que permutation suivante ...
Lorsque votre application n'est pas en cours d'exécution ou tuée et que vous appuyez sur Notification push, cette fonction se déclenchera;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
vous devez donc le gérer comme ça,
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (localNotif) {
NSString *json = [localNotif valueForKey:@"data"];
// Parse your string to dictionary
}
Il vaut mieux que vous remplaciez didReceiveRemoteNotification
C'est parti
NSDictionary * pushNotificationPayload = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(pushNotificationPayload) {
[self application:application didReceiveRemoteNotification:pushNotificationPayload];
}
Cela déclenchera à nouveau la méthode didReceiveRemoteNotification
et votre Push notification
le code s'exécutera de la même manière qu'il s'exécute pendant l'exécution de l'application.
J'ai essayé la réponse de @ dianz, cela n'a pas fonctionné pour moi mais j'ai obtenu une aide de la réponse.
Dans mon cas;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDictionary *apnsBody = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (apnsBody) {
// Do your code with apnsBody
}
J'ai eu le même problème mais j'ai finalement pu gérer la notification push lorsque le est inactif (ne fonctionne pas) à l'aide de l'extension du service de notification. Cette solution a été recommandée par Apple Team Support et ce n'est que pour iOS 10, je l'ai implémentée et ça marche bien! Je laisse le lien:
Voici la procédure:
REMARQUE: considérez que vous utiliserez trois identifiants: 1) Identifiant pour votre application (vous en avez déjà) 2) Identifiant pour votre extension (vous allez créer) 3) Identifiant pour le groupe d'applications. (vous allez créer)
Est nécessaire pour activer Groupes d'applications pour créer une ressource où vous pouvez enregistrer et lire les informations pour votre application et l'extension. Cliquez sur "Afficher le navigateur du projet". Dans la liste des cibles, sélectionnez votre projet principal. Ensuite, cliquez sur "Capacités" et activez l'option nommée "Groupes d'applications". Veuillez ajouter l'identifiant du groupe d'applications pour identifier les ressources partagées. Vous devez faire la même étape pour la cible de l'extension que vous avez créée (Sélectionner la cible de l'extension - Capacités - Activer dans "Groupes d'applications" - Ajouter le même identifiant pour le groupe d'applications)
Vous devez ajouter l'identifiant de votre extension dans Apple Developer Site pour identifier l'extension du service de notification, vous devez également créer de nouveaux profils provisoires (développement, ad hoc et/ou production) et l'associer à les nouveaux profils provisoires.
Sur les deux identifiants (application et extension), vous devez les modifier et activer le service "Groupes d'applications" dans les deux. Vous devez ajouter l'identifiant du groupe d'applications dans les services des groupes d'applications.
REMARQUE: l'identifiant pour l'application et l'identifiant pour l'extension DEVRAIENT AVOIR LE MÊME IDENTIFICATEUR POUR LE GROUPE D'APP.
Téléchargez le nouveau profil provisoire sur Xcode et associez-le à votre extension de service de notification. Veuillez vous assurer que tout va bien avec eux.
Après cela, dans "Capacités" de votre application et extension, ouvrez la section "Groupes d'applications" et mettez-les à jour. Les trois étapes - 1) Ajouter les droits des groupes d'applications à votre fichier de droits, 2) Appliquer la fonctionnalité Groupes d'applications à votre ID d'application et 3) Ajouter des groupes d'applications à votre ID d'application - doivent être vérifiées.
Revenez au navigateur de projet et sélectionnez le dossier de votre extension. Ouvrez le fichier .m. Vous verrez une méthode appelée didReceiveNotificationRequest: (UNNotificationRequest *) request. Dans cette méthode, vous allez créer un NSUserDefaults différent avec SuiteName exactement égal à l'identifiant pour le groupe d'applications comme ceci:
NSUserDefaults * defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @ "identifiant pour le groupe d'applications"];
Dans cette même méthode, récupérez le corps de la notification et enregistrez-le dans un NSMutableArray, puis enregistrez-le dans les ressources de partage. Comme ça:
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler{ self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; NSMutableArray *notifications = [NSMutableArray new]; NSUserDefaults *defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @"Identifier for app group"]; notifications = [[defaultsGroup objectForKey:@"notifications"] mutableCopy]; if (notifications != nil){ [notifications addObject:self.bestAttemptContent.userInfo]; }else{ notifications = [NSMutableArray new]; [notifications addObject:self.bestAttemptContent.userInfo]; } [defaultsGroup setObject:notifications forKey:@"notifications"]; }
NSUserDefaults *defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @"Identifier for app group"]; NSMutableArray *notifications = [[defaultsGroup objectForKey:@"notifications"] mutableCopy];
J'espère être clair à chaque étape. Je vais écrire un article pour implémenter cette solution avec des images dans ma page. Un autre point que vous devez considérer est que cela ne fonctionne pas avec la notification push silencieuse.
Bien que cela ait été répondu, aucune des réponses fournies n'a réellement fonctionné correctement. Voici mon implémentation que j'ai pu mettre au travail.
Ce code va dans application:didFinishLaunchingWithOptions:
Swift:
if let options = launchOptions, notification = options[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject : AnyObject] {
// NOTE: (Kyle Begeman) May 19, 2016 - There is an issue with iOS instantiating the UIWindow object. Making this call without
// a delay will cause window to be nil, thus preventing us from constructing the application and assigning it to the window.
Quark.runAfterDelay(seconds: 0.001, after: {
self.application(application, didReceiveRemoteNotification: notification)
})
}
Objectif-C:
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
[self application:application didReceiveRemoteNotification:launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]];
}
Quelques notes:
Peut-être en raison de la façon dont iOS met en file d'attente les allocations, l'objet racine UIApplication.sharedApplication().window
est nul lors du lancement de l'application après avoir été tué. L'ajout d'un délai de 1 milliseconde a résolu ce problème. N'a pas testé cela dans Objective-C
Le cast vers [NSObject: AnyObject] était nécessaire pour éviter d'avoir des conflits de type mais je n'ai pas beaucoup expérimenté avec cela; gardez-le à l'esprit lors de la mise en œuvre de votre propre projet. Objective-C ne l'exige pas.
Quark est juste une petite bibliothèque amusante que j'utilise dans tous mes projets qui contient des extensions et des méthodes utiles et couramment utilisées. Utilisez simplement toute forme de retard qui correspond aux besoins de votre application.
Essayez d'aller à la méthode didReceiveRemoteNotification
et de la gérer. Là, vous pouvez vérifier les états de l'application en effectuant des conditions pour applicationState
, par exemple en vérifiant s'il s'agit de UIApplicationStateActive
ou d'autres.
Swift et xCode 8.3.2:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// your code here
// Check if app was not running in background and user taps on Push Notification
// This will perform your code in didReceiveRemoteNotification where you should handle different application states
if let options = launchOptions, let notification = options[UIApplicationLaunchOptionsKey.remoteNotification] as? [NSObject : AnyObject] {
self.application(application, didReceiveRemoteNotification: notification)
}
return true
}
essaye ça
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
//register notifications
if([application respondsToSelector:@selector(registerUserNotificationSettings:)]) // ios 8
{
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
[application registerForRemoteNotifications];
}
else // ios 7
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge];
}
// open app from a notification
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification)
{
//your alert should be here
}
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
return YES;
}