天天看點

Android 8.0 通知相容

Android 8.0 引入了通知管道,其允許您為要顯示的每種通知類型建立使用者可自定義的管道。使用者界面将通知管道稱之為通知類别。targeSdk更新到26之後,所有的通知的實作都需要提供通知管道,如果不提供通知管道的話,所有通知在8.0系統上面都不能正常展示,下面來看代碼。

既然是相容,當然不能少了判斷系統版本了:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 大于等于 8.0 系統版本
    
}else { // 低于8.0 版本
   
}
           

針對8.0以上的版本 注意 建立 NotificationChannel , 并設定其建立同一 channelId,注意 這個id不能過長, 過長可能被截斷;

private final String NOTIFICATION_CHANNEL_NAME = "Service";

private final String NOTIFICATION_DESCRIPTION = "讀取位置資訊";

private NotificationManager notificationManager = null;

private NotificationChannel notificationChannel = null;

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    //Android O上對Notification進行了修改,如果設定的targetSDKVersion>=26建議使用此種方式建立通知欄
    if (null == notificationManager) {
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    }
    String channelId = "channel";
    if (notificationChannel == null) {
        notificationChannel = new NotificationChannel(channelId,
                NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
        notificationChannel.setDescription(NOTIFICATION_DESCRIPTION);
        // 設定通知出現時的閃燈(如果 android 裝置支援的話)
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(0);
        notificationManager.createNotificationChannel(notificationChannel);
  
    }
    mBuilder.setChannel(channelId);
}
   mBuilder.setPriority(0);// 設定該通知優先級
   mBuilder.setSmallIcon(R.mipmap.logo);
   mBuilder.setContentTitle(getString(R.string.app_name));
   mBuilder.setContentText(getString(R.string.app_runing));
   mBuilder.setContentIntent(intent);
   notification = mBuilder.build();

startForeground(ServiceID.ID, notification);
           

在這裡 我所相容的8.0以上機型, 通過這樣設定channel 還是會彈出 錯誤資訊:“Failed to post notification on channel "null"”;

這裡都是通過 v7包下的 NotificationCompat 建立,怎麼還會報錯并且報錯 指代的是 notification on channel null????

于是我們這樣更新一下代碼,針對8.0的 做另一種設定 channel方式:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    //Android O上對Notification進行了修改,如果設定的targetSDKVersion>=26建議使用此種方式建立通知欄
    if (null == notificationManager) {
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    }
    String channelId = "channel";
    if (notificationChannel == null) {
        notificationChannel = new NotificationChannel(channelId,
                NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
        notificationChannel.setDescription(NOTIFICATION_DESCRIPTION);
        // 設定通知出現時的閃燈(如果 android 裝置支援的話)
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(0);
        notificationManager.createNotificationChannel(notificationChannel);
  
    }
 // 這裡 針對8.0 我們如下設定 channel 
    notification = new Notification.Builder(this.getApplicationContext(),channelId) 
            .setSmallIcon(R.mipmap.logo)
            .setContentTitle(getString(R.string.app_name))
            .setContentText(getString(R.string.app_runing)).build();
}else {
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
    mBuilder.setPriority(0);// 設定該通知優先級
    mBuilder.setSmallIcon(R.mipmap.logo);
    mBuilder.setContentTitle(getString(R.string.app_name));
    mBuilder.setContentText(getString(R.string.app_runing));
    notification = mBuilder.build();
}
startForeground(ServiceID.ID, notification);
           

因為跟很多文章描述的問題不同,在此記錄讓大家參考一下。 8.0一下 通過 NotificationCompat 設定, 8.0以及以上 通過Notification 設定, 然後大家也發現 Notification 在 8.0 以後 廢棄了 一個參數的構造方法, 取代的就是多了一個 channel 的構造方法。