[Android Notification] Failed to post notification on channel & No Channel found for 原因是channelId不一致

问题:

使用 Notification 时,

1. Log 报错如下:

Line 5223: 03-07 11:49:20.121  1122  9346 E NotificationService: No Channel found for pkg=priv.xxx.demo, channelId=test, id=99, tag=null, opPkg=priv.xxx.demo, callingUid=10233, userId=0, incomingUserId=0, notificationUid=10233, notification=Notification(channel=test shortcut=null contentView=null vibrate=null sound=null defaults=0x0 flags=0x0 color=0x00000000 vis=PRIVATE)
    

2. 对应的 UI 提示:

Failed to post notification on channel "test". See log for more details.

[Android Notification] Failed to post notification on channel & No Channel found for 原因是channelId不一致_第1张图片

分析

从Log和toast上看,应该是 channelId 一致性出了问题。

问题代码

public static void sendNotice(Context context) {
        Log.i(TAG, "[sendNotice] ENTER, context = " + context);
        NotificationManager notificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        // Android O  (8.0)新增的 API about channel。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 使用NotificationChannel 类构建一个通知渠道
            NotificationChannel notificationChannel = new NotificationChannel("99", "TEMP",
                    NotificationManager.IMPORTANCE_DEFAULT);

            //通知的一些行为样式配置。
            notificationChannel.enableLights(true); //是否在launcher icon右上角展示提示点
            notificationChannel.setLightColor(Color.GREEN); //提示点颜色

            notificationManager.createNotificationChannel(notificationChannel);
        }
        Notification.Builder builder = new Notification.Builder(context,"test");
        builder.setContentTitle(context.getString(R.string.test_notification_title))
                .setContentText(context.getString(R.string.test_notification_content))
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher);
        Notification notification = builder.build();
        notificationManager.notify(99, notification);
}

问题解决

将channelId的内容统一,即问题代码中的“99”和“text”,取其一即可。

// channelId 要统一。
// channelId可以随便定义,只要保证全局唯一性就可以。
// 渠道名称是给用户看的,需要可以清楚地表达这个渠道的用途。
new NotificationChannel("99", "TEMP",
                    NotificationManager.IMPORTANCE_DEFAULT);
new Notification.Builder builder = new Notification.Builder(context,"99");

Nofitication 的用法

参考:通知概览  |  Android 开发者  |  Android Developers (google.cn)

  1. 获取 NotificationManager 对通知进行管理
  2. 构建一个通知渠道 NotificationChannel 
  3. 通过 Builder 创建 Notification ,配置其内容。
  4. 通过 manager 的notify() 显示通知

Note:关注 channelId 参数的统一

 public static void sendNotice(Context context, String channelId) {
        Log.i(TAG, "[sendNotice] ENTER, context = " + context);
        //1.获取 NotificationManager 对通知进行管理。
        NotificationManager notificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        //2.构建一个通知渠道 NotificationChannel。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && channelId != null) {
            NotificationChannel notificationChannel = new NotificationChannel(channelId, "TEMP",
                    NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(notificationChannel);
        }
        //3.通过 Builder 创建 Notification ,配置其内容。
        Notification.Builder builder = new Notification.Builder(context, channelId);
        builder.setContentTitle(context.getString(R.string.test_notification_title))
                .setContentText(context.getString(R.string.test_notification_content))
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher);
        Notification notification = builder.build();
        //4.通过 manager 的notify() 显示通知。
        notificationManager.notify(1, notification);
    }

相关源码

NotificationChannel & Notification 的内部类 Builder

//android-30\android\app\NotificationChannel.java
    /**
     * Creates a notification channel.
     *
     * @param id The id of the channel. Must be unique per package. The value may be truncated if
     *           it is too long.
     * @param name The user visible name of the channel. You can rename this channel when the system
     *             locale changes by listening for the {@link Intent#ACTION_LOCALE_CHANGED}
     *             broadcast. The recommended maximum length is 40 characters; the value may be
     *             truncated if it is too long.
     * @param importance The importance of the channel. This controls how interruptive notifications
     *                   posted to this channel are.
     */
    public NotificationChannel(String id, CharSequence name, @Importance int importance) {
        this.mId = getTrimmedString(id);
        this.mName = name != null ? getTrimmedString(name.toString()) : null;
        this.mImportance = importance;
    }
// android-30\android\app\Notification.java
       /**
         * Constructs a new Builder with the defaults:
         *
         * @param context
         *            A {@link Context} that will be used by the Builder to construct the
         *            RemoteViews. The Context will not be held past the lifetime of this Builder
         *            object.
         * @param channelId
         *            The constructed Notification will be posted on this
         *            {@link NotificationChannel}. To use a NotificationChannel, it must first be
         *            created using {@link NotificationManager#createNotificationChannel}.
         */
        public Builder(Context context, String channelId) {
            this(context, (Notification) null);
            mN.mChannelId = channelId;
        }

Other

很多教程指导都是罗列方法和代码使用案例,缺少一些关键注意点的指引。

我这样的小白有点按部就班的不解,有些坑就是新手才会碰到的。

你可能感兴趣的:(Android,AOSP,android,java,Notification)