6

I'm currently getting badge from payload. But how can i update that value.

{"aps":
    {"alert":"Notification Hub test notification2",
     "badge":1,
     "sound":"Default"}
}

when i send this it is always shows 1 in the badge number but when i go inside app and exit it's getting updated.It is because of this,

func applicationDidBecomeActive(application: UIApplication) {
        UIApplication.sharedApplication().applicationIconBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber + 1
    }

But when i send a new push notification it's again shows 1 as badge number in the icon. How should i do this, to my understand i should send updated badge when i send the payload. For that i have to deal with backend.

Is there any suggestion other than this to handle inside app?

Anushka Madushan
  • 681
  • 2
  • 12
  • 31

9 Answers9

10

If your project has a notification extension, you can do a badge setting inside it.

First of all, enable App Groups and save your badge count from the app notification service extension in UserDefaults. We are using app groups because we need to clear the badge count from AppDelegate when opening the app. Also you can set value of badge as bestAttemptContent.badge from notification service extension

In notification service extension:

if let userDefaults = UserDefaults(suiteName: "group.com.bundle.appname") {
    
    let badgeCount = userDefaults.integer(forKey: "badgeCount")
    if badgeCount > 0 {
        userDefaults.set(badgeCount + 1, forKey: "badgeCount")
        bestAttemptContent.badge = badgeCount + 1 as NSNumber
    } else {
        
        userDefaults.set(1, forKey: "badgeCount")
        bestAttemptContent.badge = 1
    }
}

In AppDelegate you can clear badge...and set value for the badge as zero on userdefaults

if let userDefaults = UserDefaults(suiteName: "group.com.bundle.appname") {
    userDefaults.set(0, forKey:"badgeCount") // "change "badgecount" to be "badgeCount"
}
UIApplication.shared.applicationIconBadgeNumber = 0
sriram hegde
  • 2,301
  • 5
  • 29
  • 43
Chinju James
  • 201
  • 3
  • 8
  • I was able to find this good article on how to set up a Notification Service https://medium.com/gits-apps-insight/processing-notification-data-using-notification-service-extension-6a2b5ea2da17 – jschweitzer Jan 30 '22 at 01:20
6

I will give my way to you :

My plan is to use KVO to listen the [UIApplication sharedApplication].applicationIconBadgeNumber

- (void)setupBadgeOperation {
    [[UIApplication sharedApplication] addObserver:self forKeyPath:@"applicationIconBadgeNumber" options:NSKeyValueObservingOptionNew context:nil];
}

And once value changed, I use [[NSNotificationCenter defaultCenter] postNotificationName:STATUS_BADGENUMBER_CHANGED object:nil] to inform the UI where needs to be modified for the change of badge.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"applicationIconBadgeNumber"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:STATUS_BADGENUMBER_CHANGED object:nil];
    }
}

There is three case of receiving a remote notification to change the [UIApplication sharedApplication].applicationIconBadgeNumber.

a. app is foreground
b. app is background
c. app is not launch

in a and b case, this method will be called:

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    void(^tapBlock)(void(^completeHandler)()) = ^(void(^completeHandler)()) { 
    // here I remove some code not related with the question
    NSNumber *badgeNumber = userInfo[@"aps"][@"badge"];
    [UIApplication sharedApplication].applicationIconBadgeNumber = badgeNumber.integerValue;
} 

in c case, there is no way to get the callback, so I will do it manually.

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[NSNotificationCenter defaultCenter] postNotificationName:STATUS_BADGENUMBER_CHANGED object:nil];
}

That's all, and works well for me.

childrenOurFuture
  • 1,889
  • 2
  • 14
  • 23
6

Here my way Swift:

1) You need to set badge ( a variable you can call it whatever you want) to zero into Firebase Realtime database once you launch the app. Plus set application.applicationIconBadgeNumber = 0. Here is how I do it in AppDelegate:

func applicationDidBecomeActive(_ application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    application.applicationIconBadgeNumber = 0

    // Reset badge number to zero
    let userID = Auth.auth().currentUser?.uid

    let dbRef = Database.database().reference()
    dbRef.child("Users Info").child(userID!).updateChildValues(["badge":"0"], withCompletionBlock: { (err, ref) in
        if err != nil {
            print(err!)
            return
        }
    })

}

2) Go to index.js where a function is triggered.

...
return admin.database().ref('/Users Info/' + owner).once('value', snapshot => {

    var ownerValue = snapshot.val();

    var badgeNumber = parseInt(ownerValue.badge) + 1;

    // Notification details.
    const payload = {
      notification: {
        title: 'You have a new request!',
        body: `A new request from ${downedBy.name}.`,
        badge:`${badgeNumber}`,
        sound: 'default',
      }
    };
    ...
    ...
    // Upload the new value of badge into Firebase to keep track of the number
    return admin.database().ref('/Users Info/' + owner).update({badge:badgeNumber});
    ...
    })
Ahmadiah
  • 476
  • 5
  • 12
  • should be voted up, its the perfect answer, I implemented it this exact way and it works fine! – Zash__ Feb 18 '18 at 11:13
3

First of all, leave it to your server guys to send you updated badge counter. Your job is only to display it, not to maintain it on your end.

You need to perform the update operations in applicationDidReceiveRemoteNotifications Delegate method like this:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]){
       let notification = userInfo["aps"] as? NSDictionary
       let badge = (notification["badge"] as String).toInt() 
       UIApplication.sharedApplication().applicationIconBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber + badge;

}

And in your DidBecomeActive method:

func applicationDidBecomeActive(application: UIApplication) {
       if(UIApplication.sharedApplication().applicationIconBadgeNumber!=0){
    UIApplication.sharedApplication().applicationIconBadgeNumber = 0
    }

This is with the assumption that your server sends you updated push badge counter. In , I'd do something like this to convey to the Server that push counter must be set to zero now:

var currentInstallation = PFInstallation.currentInstallation()
      if currentInstallation.badge != 0 {
        currentInstallation.badge = 0
        currentInstallation.save
       }

If I don't do this, Server will assume that Push has never been read yet and will increment the badge counter on their end on the next push and so on.

NSNoob
  • 5,548
  • 6
  • 41
  • 54
2

Keep your badge count in NSUserDefault for maximum availability. even if you restart your device, then also you would be able to get badge count from NSUserDefault.

When you get another payload then you could keep incrementing badge count in NSUserDefault.

Hasya
  • 9,792
  • 4
  • 31
  • 46
2

Server must increment much count in @"badge" key. When you open app, you need send request to server - Reset Push Counter (badge). In applicationDidBecomeActive method.

{"aps":
    {"alert":"Notification Hub test notification2",
     "badge":20,
     "sound":"Default"}
}
NSNoob
  • 5,548
  • 6
  • 41
  • 54
MirMiratom
  • 76
  • 3
1

Whenver we use the push notification. we have to update its badge count. Otherwise each and every time badge will be same. e.g. If you got a notification its count is 1 and you read it it will still shows badge 1. so for this you have to clear the badge. by using code like this,

  func applicationDidBecomeActive(application: UIApplication) {
        application.applicationIconBadgeNumber = 0
    }
Sagar Shirbhate
  • 801
  • 7
  • 17
1

For handling the badge best solution is use the notification extension you can create a. notification extension and also use KVO to update the badge in app. and app group for saving the number of badge and managing in app. when you get notification you can read how many notification you have and add the badge of notification to that and update your notification that its

guard let content = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
        contentHandler(request.content)
        return
    }

    if let badge = bestAttemptContent?.badge as? Int {
        let newBadge = badge + NotificationManangerBridge.shared.getTotalBadge()
        content.badge = NSNumber(value: newBadge)
        NotificationManangerBridge.shared.updateTotalBadge(badgeCount: newBadge)

    } else {
        content.badge = 0
    }
    guard let notification = bestAttemptContent?.copy() as? UNNotificationContent else { return }
    contentHandler(notification)
Nazik
  • 8,696
  • 27
  • 77
  • 123
-3

You are going in a correct direction. You will have to update badge number from your payload and that's the standard way in push notifications.

Vishal Sonawane
  • 2,637
  • 2
  • 16
  • 21