创建NotificationManager和Notification
val notificationManagerCompat = NotificationManagerCompat.from(context)
val builder: NotificationCompat.Builder = NotificationCompat.Builder(context, CHANNEL_ID)
// 清楚通知栏时的相应
.setDeleteIntent(getDeleteIntent(context))
// 设置自定义通知栏布局,support兼容包25以下,找不到此方法
// 需要使用setContent(remoteViews)
.setCustomContentView(remoteViews)
// 设置通知时间,此事件用于通知栏排序
.setWhen(System.currentTimeMillis())
// 设置通知栏被点击时的事件
.setContentIntent(getContentClickIntent(context))
// 设置优先级,低优先级可能被隐藏
.setPriority(NotificationCompat.PRIORITY_HIGH)
// 设置通知栏能否被清楚,true不能被清除,false可以被清除
.setOngoing(false)
// 设置通知栏的小图标,必需设置,否则crash
.setSmallIcon(R.drawable.notification_icon)
// 此处必须兼容android O设备,否则系统版本在O以上可能不展示通知栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
context.packageName,
TAG,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManagerCompat.createNotificationChannel(channel)
}
// channelId非常重要,不设置通知栏不展示
builder.setChannelId(context.packageName)
// 创建通知栏
val notify: Notification = builder.build()
// 通知系统展示通知栏
notificationManagerCompat.notify(TAG, NOTIFY_ID, notify)
1. 部分android O设备调用notify方法无效,即不展示通知栏。解决重点在于必须兼容android O设备,否则系统版本在O以上可能不展示通知栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
context.packageName,
TAG,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManagerCompat.createNotificationChannel(channel)
}
2. 在使用Notification展示下载进度的时候,在现在速度极快的情况下,出现了下载完成但是通知栏下载进度却处于未完成状态,即 notificationManagerCompat.notify(TAG, NOTIFY_ID, notify) 无效。
此现象的原因是因为系统通知栏对单个应用通知队列通长度进行了限制。
notify方法会将Notification加入系统的通知队列,当前应用发出的Notification数量超过50时,不再继续向系统的通知队列添加Notification,即造成了“` notificationManagerCompat.notify(TAG, NOTIFY_ID, notify) 无效的现象。处理方案是降低notify方法的调用次数,每10%进度更新一次通知栏即可。
源码中实现通知栏服务的是
frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
NotificationManager.notify()方法最终调用了NotificationManagerService中的enqueueNotificationInternal()方法
enqueueNotificationInternal中调用checkDisqualifyingFeatures方法对当前应用通知队列的长度做了校验
源码:
static final int MAX_PACKAGE_NOTIFICATIONS = 50;
private boolean checkDisqualifyingFeatures(int userId, int callingUid, int id, String tag, NotificationRecord r) {
// ...省略无数代码...
// limit the number of outstanding notificationrecords an app can have
int count = getNotificationCountLocked(pkg, userId, id, tag);
if (count >= MAX_PACKAGE_NOTIFICATIONS) {
mUsageStats.registerOverCountQuota(pkg);
Slog.e(TAG, "Package has already posted or enqueued " + count
+ " notifications. Not showing more. package=" + pkg);
return false;
}
// ...省略无数代码...
}
至此