天天看点

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 的构造方法。