Update badge with push notification while app in background

IosApple Push-Notifications

Ios Problem Overview


I have got push notification working and managed to update icon badge count when app is brought to foreground.

I am a bit confused about this though... the iPhone receives the notification and the pop up message appears to activate my app, and the badge only updates after me starting the app.

This does not sound right in terms of user experience. My understanding is that the badge count should notify the user of what needs action, through incremented count, but this does not happen until a later stage when the app is live.

So is there a way to tell the app to update its badge count when it receives push notifications and whilst being in the background?

Note that my app does not use location and that I have UIRemoteNotificationTypeBadge in the notification registration request.

Ios Solutions


Solution 1 - Ios

Since push notification are handled by iOS and not your app you can't change the application badge on receiving a push notification.

But you can send the badge number in the payload of the push notification, but the you will have to do the calculation server side.

You should read Local and Push Notification Programming Guide and especially the The Notification Payload.

The payload could look like this:

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

Now the app application badge icon will show 9.

Solution 2 - Ios

Actually in iOS 10 a remote Notification will call automatically didReceiveRemoteNotification Method in your AppDelegate.

You have 2 ways of updating the badge count in the background.
I've done this for my current app also. You don't need a Notification Service Extension either.

1st Way:

Send APS badge key with your payload to APN.
This will update the badge count according to your Integer value in your payload of badge. e.x.:

// Payload for remote Notification to APN
{
    "aps": {
        "content-available": 1,
        "alert": "Hallo, this is a Test.",
        "badge": 2, // This is your Int which will appear as badge number,
        "sound": default
    }
}
2nd Way:

You can switch your application.applicationState and update your badges Count when the applicationState is in .background. BUT you have to take care not to set the badge key parameter in your Notification payload when sending to APN e.x.

// Payload to APN as silent push notification
{
    "aps": {
        "content-available": 1
    }
}
Handle the badge Update accordingly to the application state:

Here is my working code for badge count update without badge key in the payload for APN.

func application(_ application: UIApplication, didReceiveRemoteNotification 
   userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    print("APN recieved")
    // print(userInfo)
    
    let state = application.applicationState
    switch state {
        
    case .inactive:
        print("Inactive")
        
    case .background:
        print("Background")
        // update badge count here
        application.applicationIconBadgeNumber = application.applicationIconBadgeNumber + 1
        
    case .active:
        print("Active")

    }
}
Reset badge count:

Don't forget to reset your badge count when your app gets back to active state.

func applicationDidBecomeActive(_ application: UIApplication) {
    // reset badge count
    application.applicationIconBadgeNumber = 0
}

Solution 3 - Ios

We can alter the badge number when we are in the background state by sending the "badge" parameter in the push notification package. As @rckoenes pointed out the JSON parameter for the badge must be an INTEGER.

Sample PHP code for doing the same

// Create the payload body
$body['aps'] = array(
        'alert' => $message,
        'badge' => 1,
        'sound' => 'default'
        );

badge => 1 where 1 is an integer not a string (i.e. without apostrophes)

Solution 4 - Ios

    **This is the APNS payload get back from server.**
    
    {
        "aps" : {
            "alert" : "You got your emails.",
            "badge" : 9,
            "sound" : "bingbong.aiff"
        },
        "acme1" : "bar",
        "acme2" : 42
    }

The value for key badge is automatically considered as badge count.On ios app side no need to calculate or handle the count. In above example 9 is the badge count.So your app icon will show 9.

NOTE While your app is close u can't handle badges on your own.Thats why we are using badge key from APNS Payload For better clarification about notification see documentation

if you want to reduce the badge count on your own.Decrement the count and update it yourself.as follows

Solution 5 - Ios

If you are using NotificationServiceExtension the you can update badge in that.

var bestAttemptContent : UNMutableNotificationContent? // 
bestAttemptContent.badge = 0//any no you wanna display

Every time your application receive notification your service extension will be called.Save that value in user default and display it. To share user defaults between application and extension you need to enable app group in application. Read more here

Solution 6 - Ios

Since iOS 10 you can develop a Notification Service extension for your app. It will be started by the system when you receive a notification and you can calculate a valid number for the badge and set it.

Take a look at the documentation: https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension

Solution 7 - Ios

For Firebase Cloud Messaging (FCM) it should be like this:

{
  "to": "some_token",
 
  "notification": {
    "body": "this is a body",
    "title": "this is a title",
    "badge" : 1
  }, 
  
  "priority": "high", 
}

Solution 8 - Ios

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    
    application.applicationIconBadgeNumber = 0;
    NSLog(@"userInfo %@",userInfo);
    
    for (id key in userInfo) {
        NSLog(@"key: %@, value: %@", key, [userInfo objectForKey:key]);
    }
    
    [application setApplicationIconBadgeNumber:[[[userInfo objectForKey:@"aps"] objectForKey:@"badge"] intValue]];
    NSLog(@"Badge %d",[[[userInfo objectForKey:@"aps"] objectForKey:@"badge"] intValue]);
}

Solution 9 - Ios

As @rckoenes said you will have to do the calculation server side, but how could you know when to increment the badge number value you should send in payload?.

Will when you launch the application send a message to your server indicating that the application is have been launched. So, on the server side you start again from badge=0, and while there is no messages received by server increase the badge number with every push notification payload.

Solution 10 - Ios

in apns payload have to define "content-available":1 for update badge count in background mode

func application(_ application: UIApplication, didReceiveRemoteNotification 
   userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
     

// increase badge count, but no need if you include content-available
     
application.applicationIconBadgeNumber = application.applicationIconBadgeNumber + 1

}

func applicationDidBecomeActive(_ application: UIApplication) {
    
// reset badge count
    
application.applicationIconBadgeNumber = 0

}

for eg.

"aps":{
	"alert":"Test",
	"sound":"default",
    "content-available":1
	
}

Solution 11 - Ios

in legacy its work, "badge" set count

{
  "to": "token",
  "notification": {
    "title": "Example",
    "body": "Tiene 22 actualizaciones.",
    "badge":278
  },
  "data": {
    "story_id": "story_12345",
    "count_vaca":22
  }
}

Solution 12 - Ios

After receiving remote Notification when you open App,

get current Badge number in "didBecomeActive" Method of your AppDelegate.

File using below code:

int badgeCount = [UIApplication sharedApplication].applicationIconBadgeNumber;
    badgeCount = badgeCount + 1;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAbolfoooudView Question on Stackoverflow
Solution 1 - IosrckoenesView Answer on Stackoverflow
Solution 2 - IosGkiokanView Answer on Stackoverflow
Solution 3 - IosprajulView Answer on Stackoverflow
Solution 4 - IosPrabhat PandeyView Answer on Stackoverflow
Solution 5 - IosSurjeet RajputView Answer on Stackoverflow
Solution 6 - IosMichael KrutoyarskiyView Answer on Stackoverflow
Solution 7 - IosАлександр БабичView Answer on Stackoverflow
Solution 8 - IossuviView Answer on Stackoverflow
Solution 9 - IosmustafaView Answer on Stackoverflow
Solution 10 - IosPrashant kumarView Answer on Stackoverflow
Solution 11 - IosJavier J Solis FloresView Answer on Stackoverflow
Solution 12 - IosVed GuptaView Answer on Stackoverflow