当应用程序在后台时,使用推送通知更新徽章

我已经推通知工作,并设法更新图标徽章计数时,应用程序被带到前台。

我对此有点困惑... iPhone 接收到通知,弹出消息似乎激活了我的应用程序,徽章只有在我启动应用程序后才会更新。

就用户体验而言,这听起来并不正确。我的理解是,徽章计数应该通过增量计数来通知用户需要采取什么行动,但这要等到应用程序启动后才会发生。

那么,有没有一种方法可以告诉应用程序在接收到推送通知并处于后台时更新其徽章数量呢?

请注意,我的应用程序不使用位置和我有 UIRemoteNotificationTypeBadge在通知注册请求。

119903 次浏览

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.

-(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]);
}

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)

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;

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.

    **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

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

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

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
}

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


}

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",
}

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
}
}