android呼叫NotificationManager.notify無效,通知欄不顯示
建立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)
原始碼中實現通知欄服務的是
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;
}
// ...省略無數程式碼...
}
至此