App和后台集成极光推送。
首先应该了解:
1、后台调用极光API推送消息时,传的角标值是"+1",而不是具体的某个值,估计极光传给Apns的值也是这样,这样就可以所有机型的不同通知数量进行累加。
2、直接设置applicationIconBadgeNumber角标为0,会清除所有通知。
UIApplication.shared.applicationIconBadgeNumber = 0
3、当收到通知时,接受到的数据一般为:
{
"aps" : {
"alert" : {
"body" : "content通知显示的内容",
"title" : "title通知显示的标题"
},
"badge" : 6,
"extras" : { // 自定义字段
"id" : "200",
"types" : "2"
},
"sound" : "default"
}
}
系统会获取badge的值,立刻显示为角标。因此这个字段非常重要。
一般为了显示正确的数字,在设置applicationIconBadgeNumber后,还要将这个值传给极光。这样前后台的对每台设备的角标数是统一的。
UIApplication.shared.applicationIconBadgeNumber = number
JPUSHService.setBadge(number)
4、App显示角标值由两个值决定:推送时接收的badge值和applicationIconBadgeNumber。
当点击某个通知时,如果不改变applicationIconBadgeNumber值,角标是不会变得。因此每次点击通知,必须改变角标的值。
这里有三套方案:
1、只要点击通知,在设置applicationIconBadgeNumber为0。
UIApplication.shared.applicationIconBadgeNumber = 0
JPUSHService.setBadge(0)
优点是逻辑简单,代码简单。缺点是体验不好,用户点击某个通知,所有的通知就消失了。。。虽然缺点很明显,但也有很多App是这样做的。
2、准确的计算角标
var badgeNO = UIApplication.shared.applicationIconBadgeNumber
if badgeNO > 0 {
badgeNO -= 1
UIApplication.shared.applicationIconBadgeNumber = badgeNO
JPUSHService.setBadge(badgeNO)
}
badgeNO -= 1和UIApplication.shared.applicationIconBadgeNumber = badgeNO,会减少一个单位的值,对通知栏的本App其他通知不产生影响。我猜测,通知系统维护底层一个数组,用于显示某个App的所有通知,而数组的长度由applicationIconBadgeNumber决定(其实这里的逻辑比较复杂,通知栏通知的个数应该小于等于角标的个数)。
这里必须考虑到一种需求:用户清除通知栏所有的通知,而App角标不会变化。一般在App中,构建一个消息中心的模块,用于显示用户没有读取的通知,当用户查看消息后,角标在变化,例如老虎证券就是这样做的;当然比如像微信、QQ、支付宝等,它们的消息中心是整个App界面,而不是一个单独的列表页。
3、与本地通知角标显示配合使用。(推荐)
思路:看到的显示角标数字,都是本地通知显示的角标
具体代码
/// 通过本地推送,间接处理角标显示和通知中心的逻辑:点击App,角标不显示(值为0),但是通知中心的消息不清空。
func localNotificationDealWithBadgeNumber() {
let ln = UILocalNotification() // 自己产生本地通知
ln.applicationIconBadgeNumber = -1 // 设置数量
UIApplication.shared.presentLocalNotificationNow(ln)
JPUSHService.setBadge(0) // 给极光的发送角标数量
}
该方法在applicationWillResignActive和applicationDidEnterBackground中调用。
大体上友好地解决了该问题。该方案应该是我参考网友的。