原文鏈接: https://blog.csdn.net/dandelionela/article/details/86092293
寫了一個前臺通知,在Android5.0設備上測試沒問題,換到8.0之後報錯:
- android.app.RemoteServiceException: Bad notification for startForeground:
- java.lang.RuntimeException: invalid channel for service notification:
- Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE)
查看資料:https://blog.csdn.net/misiyuan/article/details/78384819
原來是Android8.0對通知做了細分,引進了channel,這主要影響兩個方面:
A。普通通知Notification;B。前臺服務通知
而我遇到的就是後者。
A.普通通知Notification:
對於普通通知,對於Android 8.0的適配可參照:https://blog.csdn.net/qq_34773981/article/details/78173376
主要相對於傳統的寫法修改兩處:
①在“NotificationManager”中設置添加“NotificationChannel”屬性:
- NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
-
- // 【適配Android8.0】給NotificationManager對象設置NotificationChannel
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- NotificationChannel channel = new NotificationChannel("notification_id", "notification_name", NotificationManager.IMPORTANCE_LOW);
- notificationManager.createNotificationChannel(channel);
- }
②在“Notification”中使用“setChannelId()”方法設置添加“channel_id”屬性:
- NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
- ...
- ...
- // 【適配Android8.0】設置Notification的Channel_ID,否則不能正常顯示
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- builder.setChannelId("notification_id");
- }
- ...
- builder.build();
其中,第①步驟中的“NotificationChannel”的構造函數中參數列表依次爲:
【channel_id】唯一id,String類型;
【channel_name】對用戶可見的channel名稱,String類型;
【importance_level】通知的重要程度。
importance_level主要有七種層次:
IMPORTANCE_NONE: (0)關閉通知。在任何地方都不會顯示,被阻塞
IMPORTANCE_MIN: (1)開啓通知。不彈出,不發提示音,狀態欄中無顯示
IMPORTANCE_LOW: (2)開啓通知。不彈出,不發提示音,狀態欄中顯示
IMPORTANCE_DEFAULT:(3)開啓通知。不彈出,發出提示音,狀態欄中顯示【默認】
IMPORTANCE_HIGH: (4)開啓通知。會彈出,發出提示音,狀態欄中顯示
IMPORTANCE_MAX: (5)開啓通知。會彈出,發出提示音,可以使用full screen intents(比如來電)。重要程度最高
IMPORTANCE_UNSPECIFIED:(-1000)表示用戶未設重要值。該值是爲了持久的首選項,且永不應該與實際通知相關聯
該部分參考:
①https://blog.csdn.net/Haienzi/article/details/81268022 【標題:Android8.0使用通知創建前臺服務】
②https://www.jianshu.com/p/f85ef58edf63 【標題:Android Oreo 通知新特性,這坑老夫先踩了】
前世今生:
Android O之前,叫通知“優先級”,通過在Build時,setPriority() 設置,共分爲5檔(-2 ~ 2);
默認值:Notification.PRIORITY_DEFAULT
Android O之後,叫通知“重要性”,通過NotificationChannel的 setImportance() 設置,也是5檔(0 ~ 4);
默認值:NotificationManager.IMPORTANCE_DEFAULT
即使你設置了通知聲音、震動這些屬性,其“重要性”也必須滿足下表對應的檔位:
Importance | Behavior | Usage | Examples |
NONE | Don't show in the shade | Normally, Suppressing notification from package by user request | Blocked apps notification |
MIN | No sound or visual interruption | Non-essential information that can wait or isn’t specifically relevant to the user | Nearby places of interest, weather, promotional content |
LOW | No sound | Notification channels that don't meet the requirements of other importance levels | New content the user has subscribed to, social network invitations |
DEFAULT | Makes a sound | Information that should be seen at the user’s earliest convenience, but not interrupt what they're doing | Traffic alerts, task reminders |
HIGH | Makes a sound and appears on screen | Time-critical information that the user must know, or act on, immediately | Text messages, alarms, phone calls |
該部分參考: https://www.jianshu.com/p/99bc32cd8ad6 【標題:NotificationChannel 適配填坑指南】
B.前臺服務通知:
與前者需要添加的代碼相同。
前臺服務可通過【startForeground()】方法在通知欄列出前臺服務的通知,在傳統的寫法中類似於普通通知Notification的寫法,但是不需要使用NotificationManager來管理顯示通知。但是在Android8.0之後引入NotificationChannel之後,即使找不到NotificationManager的使用位置,也是要把【A.普通通知Notification---->①在“NotificationManager”中設置添加“NotificationChannel”屬性】中的代碼在執行【startForeground();】語句之前寫出來。
- Intent intent = new Intent(this, TestActivity.class);
- PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
-
- NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
- builder.setSmallIcon(R.drawable.ic_launcher);
- builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
- ...
- ...
- // 【適配Android8.0】設置Notification的Channel_ID,否則不能正常顯示
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- builder.setChannelId("notification_id");
- }
- ...
- ...
-
-
- // 額外添加:
- // 【適配Android8.0】給NotificationManager對象設置NotificationChannel
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
- NotificationChannel channel = new NotificationChannel("notification_id", "notification_name", NotificationManager.IMPORTANCE_LOW);
- notificationManager.createNotificationChannel(channel);
- }
-
- // 啓動前臺服務通知
- startForeground(1, builder.build());
-