web-dev-qa-db-fra.com

didReceiveRemoteNotification en arrière-plan

Ce type de question a été posé à plusieurs reprises, mais je suis confronté à une situation particulière.

Lorsque mon application est active et que je reçois un message Push, je parviens à analyser les données utiles personnalisées, etc.

Cependant, lorsque mon application est en arrière-plan et que le Push arrive, l'utilisateur doit cliquer sur le bouton "Afficher/Ouvrir" pour que la didReceiveRemoteNotification soit appelée et la didFinishLaunchingWithOptions ensuite appelée.

Je dois laisser mon application décider si elle doit inviter l'utilisateur avec un UIAlert en arrière-plan ou supprimer le message Push en fonction de certains paramètres locaux.

Toute aide serait appréciée,

49
Erwin

Votre application doit gérer tous les états possibles de livraison des notifications Push:

  • Votre application vient d'être lancée

  • Votre application vient d'être portée du fond au premier plan

  • Votre application fonctionnait déjà au premier plan

Vous ne pouvez pas choisir au moment de la livraison quelle méthode de présentation est utilisée pour présenter la notification Push, qui est codée dans la notification elle-même (alerte facultative, numéro de badge, son). Mais étant donné que vous contrôlez probablement à la fois l'application et la charge utile de la notification Push, vous pouvez spécifier dans la charge utile s'il existe ou non une vue d'alerte et un message déjà présentés à l'utilisateur. Ce n'est que dans le cas où l'application est déjà en cours d'exécution au premier plan que vous savez que l'utilisateur n'a pas simplement lancé votre application via une alerte ou régulièrement à partir de l'écran d'accueil.

Vous pouvez savoir si votre application a été mise au premier plan ou non dans didReceiveRemoteNotification à l'aide de ce morceau de code:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    if ( application.applicationState == UIApplicationStateActive )
        // app was already in the foreground
    else
        // app was just brought from background to foreground
    ...
}
148
Bogatyr

Passez content-available = 1 avec votre charge utile et invoquerez didReceiveRemoteNotification même en arrière-plan. par exemple.

{
    "alert" : "",
    "badge" : "0",
    "content-available" : "1",
    "sound" : ""
}
13
Sandeep Kumar

Vous devez effectuer plusieurs opérations pour gérer la notification Push reçue lorsque l'application est en arrière-plan.

Premièrement, côté serveur, vous devez définir {"aps":{"content-available" : 1... / $body['aps']['content-available'] =1; dans la charge de notification Push. 

Deuxièmement, dans votre projet Xcode, vous devez adapter les "notifications à distance". Pour ce faire, accédez à la cible du projet -> capacités, puis activez le commutateur de capacités et cochez la case des notifications à distance.

Troisièmement, au lieu d'utiliser didReceiveRemoteNotification, vous devez appeler application:didReceiveRemoteNotification:fetchCompletionHandler:. Cela vous permettra d'effectuer les tâches que vous souhaitez effectuer en arrière-plan, au moment de la réception de la notification:

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

 if(application.applicationState == UIApplicationStateInactive) {

     NSLog(@"Inactive - the user has tapped in the notification when app was closed or in background");
     //do some tasks
    [self manageRemoteNotification:userInfo];
     completionHandler(UIBackgroundFetchResultNewData);
 }
 else if (application.applicationState == UIApplicationStateBackground) {

     NSLog(@"application Background - notification has arrived when app was in background");
     NSString* contentAvailable = [NSString stringWithFormat:@"%@", [[userInfo valueForKey:@"aps"] valueForKey:@"content-available"]];

     if([contentAvailable isEqualToString:@"1"]) {
         // do tasks
         [self manageRemoteNotification:userInfo];
         NSLog(@"content-available is equal to 1");
         completionHandler(UIBackgroundFetchResultNewData);
     }
 }
 else {
     NSLog(@"application Active - notication has arrived while app was opened");
        //Show an in-app banner
         //do tasks
        [self manageRemoteNotification:userInfo];
         completionHandler(UIBackgroundFetchResultNewData);
     }
 }

Enfin, vous devez ajouter ce type de notification: UIRemoteNotificationTypeNewsstandContentAvailability aux paramètres de notification lorsque vous le définissez.

En dehors de cela, si votre application a été fermée lorsque la notification est arrivée, vous devez gérer cela dans didFinishLaunchingWithOptions, et si l'utilisateur appuie sur la notification Push:

if (launchOptions != nil)
{
    NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

    if (dictionary != nil)
    {
        NSLog(@"Launched from Push notification: %@", dictionary);
        [self manageRemoteNotification:dictionary];
    }
}

launchOptions est! = nil lorsque vous lancez l'application en appuyant sur la notification Push, si vous y accédez en appuyant sur l'icône, launchOptions sera == nul.

J'espère que cela vous sera utile. Ici, il est expliqué par Apple .

11
AlbertoC

Une chose à garder à l'esprit, lorsque votre message Push arrive sur l'iPhone de l'utilisateur et que celui-ci clique sur "annuler", à l'exception du numéro de badge de l'icône (ils seront pris en charge par le système d'exploitation), il n'y aurait aucun moyen de vous -L'application d'arrière-plan pour connaître cet événement Push et entreprendre d'autres actions.

7
Di Wu

Mot d'avertissement

Je pense que la logique de votre application fonde le comportement sur des données personnalisées dans votre notification Push. Ce n’est pas ce à quoi les notifications push sont destinées. Ce que vous devriez également faire sur didbecomeactive dans votre application est simplement de demander à votre serveur les données dont vous avez besoin et que vous envoyiez quand même en tant que charge utile, et vous fiez à cela au lieu de votre charge utile. 

Parce que la documentation indique également cela en tant que meilleure pratique. Parce qu'Apple ne garantit pas que votre notification Push soit reçue 100% du temps de toute façon. 

Important: la remise des notifications est un «effort maximum», pas garanti. Il n'est pas destiné à transmettre des données à votre application, mais uniquement à informer l'utilisateur que de nouvelles données sont disponibles.

Toutefois, si vous souhaitez savoir si, par exemple, le badge a été modifié sans que l'utilisateur ouvre l'application en cliquant sur le badge, vous pouvez obtenir la configuration suivante:

A. vous ajoutez un numéro de badge (correct) à la charge de la notification Push envoyée par votre serveur. Cela pourrait par exemple ressembler à ceci:

{
    "aps" : {
        "alert" : "You got your emails.",
        "badge" : 9
    }
}

B. vous surveillez ce numéro de manière persistante dans votre application, par exemple en le stockant dans NSUserDefaults

Ensuite, dans applicationDidBecomeActive, vous pourrez comparer la propriété applicationIconBadgeNumber de UIApplication avec le nombre de badges que vous avez précédemment stocké, voir si elle a été augmentée ou réduite et effectuer des mises à jour en conséquence.

 - (void)applicationDidBecomeActive:(UIApplication *)application
    {

        NSNumber *badgecount = [[NSUserDefaults standardUserDefaults] objectForKey:@"badgecount"];
        if (!badgecount) badgecount = @(0);

        if ([UIApplication sharedApplication].applicationIconBadgeNumber != [badgecount integerValue]) {
            //store the new badge count
            badgecount = [NSNumber numberWithInteger:[UIApplication sharedApplication].applicationIconBadgeNumber];
            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
            [defaults setObject:badgecount forKey:@"badgecount"];
            [defaults synchronize];

            // do some stuff here because it's different
        }

    }
2
morksinaanab

Depuis la récente iOS - je pense 8 - si les notifications à distance sont activées en mode d’arrière-plan, une astuce consiste à déterminer si vous entrez le premier plan en tant qu’indicateur.

@interface AppDelegate ()

@property (assign, atomic, getter=isEnteringForeground) BOOL enteringForeground;

@end

- (void) applicationWillEnterForeground: (UIApplication *) application
{
    self.enteringForeground = YES;
}

- (void) applicationDidBecomeActive: (UIApplication *) application
{
    self.enteringForeground = NO;
}

- (void) application: (UIApplication *) application didReceiveRemoteNotification: (NSDictionary *) userInfo fetchCompletionHandler: (void (^) (UIBackgroundFetchResult)) completionHandler
{
    const BOOL launchedFromBackground = !(application.applicationState == UIApplicationStateActive);
    const BOOL enteringForeground = self.enteringForeground;

    if (launchedFromBackground && enteringForeground) {
        // The user clicked a Push while the app was in the BG
    }
}
0
mszaro