iphone - icon - android notification set badge number




iPhone: Incrémenter le badge de l'application via une notification locale (7)

Ajoutez le code suivant dans votre délégué de projet.

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    NSLog(@"%s",__FUNCTION__);

    NSArray *arrayOfLocalNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications] ;

    for (UILocalNotification *localNotification in arrayOfLocalNotifications) {
        NSLog(@"the notification: %@", localNotification);
        localNotification.applicationIconBadgeNumber= application.applicationIconBadgeNumber+1;
    }
}

cela fonctionne pour moi. :-)

est-il possible d'incrémenter le badge d'application via une notification locale alors que l'application n'est pas en cours d'exécution?

Je sais comment définir le badge, mais je n'ai trouvé aucun moyen d'incrémenter cette valeur.

localNotification.applicationIconBadgeNumber = 23;

Mise à jour: J'ai trouvé une solution (loin d'être parfaite). Vous pouvez prédire ce qui se passera si l'utilisateur n'ouvre pas l'application et ajoute des notifications pour chaque événement +1.

Un exemple:

  • Pour le jour 1: Count = 0
  • Pour le jour 2: localNotification.applicationIconBadgeNumber = 1;
  • Pour le jour 3: localNotification.applicationIconBadgeNumber = 2;
  • Pour le jour 4: localNotification.applicationIconBadgeNumber = 3;

==> Mettez ces notifications dans un tableau et définissez-les avant la fermeture de l'application.

Cependant, je cherche une meilleure solution que cette solution de contournement.


Basé sur Wassaahbbs et Bionicles réponses ci-dessus. Swift 4.0, pour toutes les versions iOS. Appelez cette fonction dans func applicationDidBecomeActive(_ application: UIApplication) .

func renumberBadgesOfPendingNotifications() {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().getPendingNotificationRequests { pendingNotificationRequests in
            if pendingNotificationRequests.count > 0 {
                let notificationRequests = pendingNotificationRequests
                    .filter { $0.trigger is UNCalendarNotificationTrigger }
                    .sorted(by: { (r1, r2) -> Bool in
                        let r1Trigger = r1.trigger as! UNCalendarNotificationTrigger
                        let r2Trigger = r2.trigger as! UNCalendarNotificationTrigger
                        let r1Date = r1Trigger.nextTriggerDate()!
                        let r2Date = r2Trigger.nextTriggerDate()!

                        return r1Date.compare(r2Date) == .orderedAscending
                    })

                let identifiers = notificationRequests.map { $0.identifier }
                UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: identifiers)

                notificationRequests.enumerated().forEach { (index, request) in
                    if let trigger = request.trigger {
                        let content = UNMutableNotificationContent()
                        content.body = request.content.body
                        content.sound = .default()
                        content.badge = (index + 1) as NSNumber

                        let request = UNNotificationRequest(identifier: request.identifier, content: content, trigger: trigger)
                        UNUserNotificationCenter.current().add(request)
                    }
                }
            }
        }
    } else if let pendingNotifications = UIApplication.shared.scheduledLocalNotifications, pendingNotifications.count > 0 {
        let notifications = pendingNotifications
            .filter { $0.fireDate != nil }
            .sorted(by: { n1, n2 in n1.fireDate!.compare(n2.fireDate!) == .orderedAscending })

        notifications.forEach { UIApplication.shared.cancelLocalNotification($0) }
        notifications.enumerated().forEach { (index, notification) in
            notification.applicationIconBadgeNumber = index + 1
            UIApplication.shared.scheduleLocalNotification(notification)
        }
    }
}

J'ai trouvé, implémenté et testé une «solution de contournement» pour (apparemment) auto-incrémenter le numéro de badge de l'icône de l'application, ce qui fonctionne bien avec les notifications locales non répétitives

Il est en effet impossible pour UILocalNotifications de mettre iOS à jour / incrémenter automatiquement le numéro de badge lorsque plusieurs notifications locales sont déclenchées et que l'utilisateur les "ignore" ou ne les gère pas immédiatement, de sorte qu'elles "s'accumulent" dans la notification. centre.

De plus, l'ajout d'une méthode de rappel à votre application ne peut pas prendre en charge l'incrémentation automatique, car l'intégralité de la notification est traitée en dehors de votre application par iOS, votre application n'a même pas besoin d'être exécutée.

Cependant, il existe une solution de contournement, basée sur les connaissances que j'ai trouvées lors de l'expérimentation, car la documentation XCode est trop vague sur la propriété du badge.

  • le badge est juste un «entier», en fait plus comme une «étiquette factice» que vous attribuez à la propriété applicationIconBadgeNumber, juste avant l'enregistrement de la notification. Vous pouvez lui donner une valeur - lorsque la notification se déclenche, iOS ajoutera cette valeur au badge, quelle que soit la valeur définie au moment de l'enregistrement de la notification. Il n'y a pas de magie "auto-incrémentation" ou autre manipulation par iOS (peut-être que c'est différent avec les notifications push, mais ce n'est pas le sujet ici). iOS prend simplement le nombre (entier) de la notification enregistrée et le place dans le badge.

Ainsi, pour une «solution de contournement», votre application doit déjà fournir le numéro de badge incrémenté correct pour chaque notification qu'elle crée et enregistre «en plus des notifications en attente».

Comme votre application ne peut pas regarder dans le futur, et de savoir quels événements vous allez gérer immédiatement, et quels sont ceux que vous laisserez en suspens pendant un certain temps, il y a un truc à faire:

Lorsque les notifications sont gérées par votre application (en tapant sur la notification, l'icône, ...), vous devez:

  1. obtenir une copie de toutes les notifications en attente
  2. 'renuméroter' le numéro de badge de ces notifications en attente
  3. supprimer toutes les notifications en attente
  4. réenregistrer la copie des notifications avec leurs numéros de badge corrigés

De plus, lorsque votre application enregistre une nouvelle notification, elle doit d'abord vérifier le nombre de notifications en attente et enregistrer la nouvelle notification avec:

badgeNbr = nbrOfPendingNotifications + 1;

En regardant mon code, cela deviendra plus clair. J'ai testé ça et ça marche vraiment:

Dans votre méthode 'registerLocalNotification', vous devriez faire ceci:

NSUInteger nextBadgeNumber = [[[UIApplication sharedApplication] scheduledLocalNotifications] count] + 1;
localNotification.applicationIconBadgeNumber = nextBadgeNumber;

Lorsque vous gérez la notification (appDelegate), vous devez appeler la méthode ci-dessous, qui efface le badge sur l'icône et renumérote les badges pour les notifications en attente (le cas échéant).

Notez que le code suivant fonctionne correctement pour les événements enregistrés «séquentiels». Si vous "ajoutez" des événements entre ceux en attente, vous devrez d'abord "trier" ces événements. Je ne suis pas allé aussi loin, mais je pense que c'est possible.

- (void)renumberBadgesOfPendingNotifications
{
    // clear the badge on the icon
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];

    // first get a copy of all pending notifications (unfortunately you cannot 'modify' a pending notification)
    NSArray *pendingNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications];

    // if there are any pending notifications -> adjust their badge number
    if (pendingNotifications.count != 0)
    {
        // clear all pending notifications
        [[UIApplication sharedApplication] cancelAllLocalNotifications];

        // the for loop will 'restore' the pending notifications, but with corrected badge numbers
        // note : a more advanced method could 'sort' the notifications first !!!
        NSUInteger badgeNbr = 1;

        for (UILocalNotification *notification in pendingNotifications)
        {
            // modify the badgeNumber
            notification.applicationIconBadgeNumber = badgeNbr++;

            // schedule 'again'
            [[UIApplication sharedApplication] scheduleLocalNotification:notification];
        }
    }
}

Pour être vraiment «à l'épreuve des balles», cette méthode devrait être du code «atomique» (noyau), empêchant l'iOS de déclencher une notification lors de l'exécution de cette méthode. Nous devrons prendre ce risque ici, les chances sont très petites que cela se produise.

Ceci est ma première contribution à , vous pouvez donc aussi commenter si je ne suis pas les règles ici


La réponse de Whasssaaahhh m'a été très utile. J'ai également eu besoin de trier les notifications en fonction de leurs fireDate. Voici le code de Whasssaaahhh avec mon code pour trier les notifications en utilisant la méthode déléguée de NSArray pour le tri - [NSArray sortedArrayUsingComparator:^(id obj1, id obj2) {}];

- (void)renumberBadgesOfPendingNotifications
{
    // clear the badge on the icon
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];

    // first get a copy of all pending notifications (unfortunately you cannot 'modify' a pending notification)
    // Sort the pending notifications first by their fireDate
    NSArray *pendingNotifications = [[[UIApplication sharedApplication] scheduledLocalNotifications] sortedArrayUsingComparator:^(id obj1, id obj2) {
        if ([obj1 isKindOfClass:[UILocalNotification class]] && [obj2 isKindOfClass:[UILocalNotification class]])
        {
            UILocalNotification *notif1 = (UILocalNotification *)obj1;
            UILocalNotification *notif2 = (UILocalNotification *)obj2;
            return [notif1.fireDate compare:notif2.fireDate];
        }

        return NSOrderedSame;
    }];

    // if there are any pending notifications -> adjust their badge number
    if (pendingNotifications.count != 0)
    {
        // clear all pending notifications
        [[UIApplication sharedApplication] cancelAllLocalNotifications];

        // the for loop will 'restore' the pending notifications, but with corrected badge numbers
        // note : a more advanced method could 'sort' the notifications first !!!
        NSUInteger badgeNbr = 1;

        for (UILocalNotification *notification in pendingNotifications)
        {
            // modify the badgeNumber
            notification.applicationIconBadgeNumber = badgeNbr++;

            // schedule 'again'
            [[UIApplication sharedApplication] scheduleLocalNotification:notification];
        }
    }
}

Après un certain temps, j'avais besoin de l'implémenter sur Swift mais aussi de prendre en charge la répétition des notifications locales . J'ai trouvé une solution sur Swift.

Solution pour Swift 2.3

func renumberBadgesOfPendingNotifications() {
    let app = UIApplication.sharedApplication()
    let pendingNotifications = app.scheduledLocalNotifications

    // clear the badge on the icon
    app.applicationIconBadgeNumber = 0

    // first get a copy of all pending notifications (unfortunately you cannot 'modify' a pending notification)
    // if there are any pending notifications -> adjust their badge number
    if let pendings = pendingNotifications where pendings.count > 0 {

        // Reassign firedate.
        var notifications = pendings
        var i = 0
        for notif in notifications {
            if notif.fireDate?.compare(NSDate()) == NSComparisonResult.OrderedAscending &&
            notif.repeatInterval.rawValue == NSCalendarUnit.init(rawValue:0).rawValue {
                // Skip notification scheduled earlier than current date time
                // and if it is has NO REPEAT INTERVAL
            }
            else {
                notif.fireDate = getFireDate(notif)
            }

            i+=1
        }

        // sorted by fire date.
        notifications = pendings.sort({ p1, p2 in p1.fireDate!.compare(p2.fireDate!) == .OrderedAscending })

        // clear all pending notifications
        app.cancelAllLocalNotifications()

        // the for loop will 'restore' the pending notifications, but with corrected badge numbers
        var badgeNumber: Int = 1
        for n in notifications {
            // modify the badgeNumber
            n.applicationIconBadgeNumber = badgeNumber

            badgeNumber+=1
            // schedule 'again'
            app.scheduleLocalNotification(n)
        }
    }
}

private func getFireDate(notification:UILocalNotification?) -> NSDate? {
        if notification == nil {
            return nil
        }

        let currentDate: NSDate = NSDate().dateByRemovingSeconds()
        let originalDate: NSDate = notification!.fireDate!
        var fireDate: NSDate? = originalDate

        if originalDate.compare(currentDate) == NSComparisonResult.OrderedAscending ||
            originalDate.compare(currentDate) == NSComparisonResult.OrderedSame {

            let currentDateTimeInterval = currentDate.timeIntervalSinceReferenceDate
            let originalDateTimeInterval = originalDate.timeIntervalSinceReferenceDate
            var frequency:NSTimeInterval = 0

            switch notification?.repeatInterval {
            case NSCalendarUnit.Hour?:
                frequency = currentDate.dateByAddingHours(1).timeIntervalSinceDate(currentDate)
                print(frequency)
                break
            case NSCalendarUnit.Day?:
                frequency = currentDate.dateByAddingDays(1).timeIntervalSinceDate(currentDate)
                print(frequency)
                break
            case NSCalendarUnit.WeekOfYear?:
                frequency = currentDate.dateByAddingDays(7).timeIntervalSinceDate(currentDate)
                print(frequency)
                break
            case NSCalendarUnit.Month?:
                frequency = currentDate.dateByAddingMonths(1).timeIntervalSinceDate(currentDate)
                print(frequency)
                break
            case NSCalendarUnit.Year?:
                frequency = currentDate.dateByAddingYears(1).timeIntervalSinceDate(currentDate)
                print(frequency)
                break
            default:
                originalDate
            }

            let timeIntervalDiff = (((currentDateTimeInterval - originalDateTimeInterval) / frequency) + frequency) + originalDateTimeInterval
            fireDate = NSDate(timeIntervalSinceReferenceDate: timeIntervalDiff)
        }

        return fireDate?.dateByRemovingSeconds()
    }

Remarque: dateByAddingHours, dateByAddingHours, dateByAddingMonths, dateByAddingYears, dateByRemovingSeconds sont des méthodes d'un DateExtension que j'utilise et sont des méthodes auto-descriptives que vous pouvez implémenter vous-même.


La seule façon de définir dynamiquement le numéro de badge lorsque votre application n'est pas en cours d'exécution est d'utiliser les notifications push. Vous devrez suivre les mises à jour du côté serveur.


Sur la base de la documentation , je pense que vous ne pouvez pas augmenter la valeur du badge lorsque votre application ne fonctionne pas. Vous définissez le numéro de badge lorsque vous planifiez votre notification, il est donc impossible de l'incrémenter.

Une application est chargée de gérer le numéro de badge affiché sur son icône. Par exemple, si une application de messagerie texte traite tous les messages entrants après avoir reçu une notification locale, elle doit supprimer le badge icône en définissant la propriété applicationIconBadgeNumber de l'objet UIApplication sur 0.


depuis iOS10, il est possible de définir le numéro de badge directement sur le UNMutableNotificationContent.

Voici ce qui fonctionne pour moi:

Je travaille sur une application qui ajoute une notification basée sur une date (avec CalendarComponents), mon déclencheur est UNCalendarNotificationTrigger. Mon code est simplement:

let content = UNMutableNotificationContent()
        content.title = "Title"
        content.body = "Your message"
        content.sound = .default()
        content.badge = NSNumber(value: UIApplication.shared.applicationIconBadgeNumber + 1)

A propos de content.badge , le doc dit:

var badge: NSNumber? { se mettre }

Description Numéro à appliquer à l'icône de l'application.

Utilisez cette propriété pour spécifier le nombre à appliquer à l'icône de l'application lorsque la notification arrive. Si votre application n'est pas autorisée à afficher les notifications par badge, cette propriété est ignorée.

Indiquez le numéro 0 pour supprimer le badge actuel, le cas échéant. Spécifiez un nombre supérieur à 0 pour afficher un badge avec ce numéro. Spécifiez nil pour laisser le badge actuel inchangé.

SDK iOS 10.0+, tvOS 10.0+, watchOS 3.0+

Le badge s'incrémente automatiquement lorsqu'une notification est ajoutée même si l'application n'est pas en cours d'exécution. Vous pouvez effacer le numéro de badge où vous voulez dans l'application avec:

UIApplication.shared.applicationIconBadgeNumber = 0






uilocalnotification