前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(一百六十八)为应用绑定通知渠道并展示消息角标

Android开发笔记(一百六十八)为应用绑定通知渠道并展示消息角标

作者头像
aqi00
发布2022-03-09 14:01:17
1.6K0
发布2022-03-09 14:01:17
举报
文章被收录于专栏:老欧说安卓老欧说安卓

为了分清消息通知的轻重缓急,从Android8开始新增了通知渠道,并且必须指定通知渠道才能正常推送消息。一个应用允许拥有多个通知渠道,每个渠道的重要性各不相同,有的渠道消息在通知栏被折叠成小行,有的渠道消息在通知栏展示完整的大行,有的渠道消息甚至会短暂悬浮于屏幕顶部,有的渠道消息在推送时会震动手机,有的渠道消息在推送时会发出铃声,有的渠道消息则完全静默推送,这些提示差别都有赖于通知渠道的特征管理。如果不考虑定制渠道特性,仅仅弄个默认渠道好推送消息,那么只需以下三行代码即可创建默认的通知渠道:

代码语言:javascript
复制
        // 从系统服务中获取通知管理器
        NotificationManager notifyMgr = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
        // 创建指定编号、指定名称、指定级别的通知渠道
        NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
        // 创建指定的通知渠道
        notifyMgr.createNotificationChannel(channel);

有了通知渠道之后,在推送消息之前使用该渠道创建对应的通知构造器,接着就能按照原方式推送消息了。使用通知渠道创建通知构造器的代码示例如下:

代码语言:javascript
复制
        // 创建一个通知消息的构造器
        Notification.Builder builder = new Notification.Builder(this);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 8.0开始必须给每个通知分配对应的渠道
            builder = new Notification.Builder(this, channelId);
        }

当然以上代码没有指定通知渠道的具体特征,消息通知的展示情况与提示方式完全按照系统默认的。若要个性化定制不同渠道的详细特征,就得单独设置渠道对象的各特征属性。下面便是NotificationChannel提供的属性设置方法说明: setSound:设置推送通知之时的铃声,若设为null表示静音推送。 enableLights:推送消息时是否让呼吸灯闪烁。 enableVibration:推送消息时是否让手机震动。 setShowBadge:是否在应用图标的右上角展示小红点。 setLockscreenVisibility:设置锁屏时候的可见性,可见性的取值说明有:VISIBILITY_PUBLIC显示所有通知内容,Notification.VISIBILITY_PRIVATE只显示标题,Notification.VISIBILITY_SECRET不显示任何内容。 setImportance:设置通知渠道的重要性,其实NotificationChannel的构造方法已经传入了重要性,所以该方法只在变更重要性时调用。重要性的取值说明包括:IMPORTANCE_MIN最小级别,IMPORTANCE_LOW低重要性,IMPORTANCE_DEFAULT默认重要性,IMPORTANCE_HIGH高重要性。

值得注意的是,每个通知渠道一经创建,就不可重复创建,即使创建也是做无用功。因此在创建渠道之前,最好先调用通知管理器的getNotificationChannel方法,判断是否存在该编号的通知渠道,只有不存在的情况才要创建通知渠道。下面是通知渠道的创建代码例子:

代码语言:javascript
复制
    // 创建通知渠道。Android 8.0开始必须给每个通知分配对应的渠道
    public static void createNotifyChannel(Context ctx, String channelId, String channelName, int importance) {
        // 从系统服务中获取通知管理器
        NotificationManager notifyMgr = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
        if (notifyMgr.getNotificationChannel(channelId) == null) { // 已经存在指定编号的通知渠道
            // 创建指定编号、指定名称、指定级别的通知渠道
            NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
            channel.setSound(null, null); // 设置推送通知之时的铃声。null表示静音推送
            channel.enableLights(true); // 通知渠道是否让呼吸灯闪烁
            channel.enableVibration(true); // 通知渠道是否让手机震动
            channel.setShowBadge(true); // 通知渠道是否在应用图标的右上角展示小红点
            // VISIBILITY_PUBLIC显示所有通知内容,Notification.VISIBILITY_PRIVATE只显示标题,Notification.VISIBILITY_SECRET不显示任何内容
            channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); // 设置锁屏时候的可见性
            channel.setImportance(importance); // 设置通知渠道的重要性级别
            // 创建指定的通知渠道
            notifyMgr.createNotificationChannel(channel);
        }
    }

尽管通知渠道提供了多种属性设置方法,但真正常用的莫过于重要性这个特征,各重要性对应的消息外观从左到右分别如下图所示,其中左图为IMPORTANCE_MIN最小级别时候的通知栏,中图为IMPORTANCE_DEFAULT默认重要性时候的通知栏,右图为IMPORTANCE_HIGH高重要性时候的顶部悬浮窗。

自从有了通知渠道,许多应用纷纷申请了多个渠道,每个渠道又有好几条消息,加起来便是许多消息。这么多的未读消息,空间有限的通知栏已然不够容纳,于是各应用又希望向用户提示未读消息的数量,好让用户知晓有没有未读消息,还有几条未读消息。 原本通知渠道提供了setShowBadge方法,可设置是否在应用图标的右上角展示小红点(此红点又称消息角标),调用该方法设置true之后,有未读消息时就显示红点,无未读消息则不显示红点。然而setShowBadge方法在国产手机上并不奏效,原因有二:其一,该方法只显示红点未显示数量;其二,该方法迟至Android8.0之后才跟着通知渠道一起推出,众多国内厂商等来不及故而早早推出了自己的红点方案。时至今日,国产手机的四大厂商包括华为、小米、OPPO、VIVO均推出了自己的消息角标方案,完全把Android官方的setShowBadge方法晾在一旁。国产手机的红点方案参考了苹果手机的红点样式,同样把消息红点放在桌面应用的右上角,并且红点内部显示当前未读消息的数量(如下面左图所示),而安卓官方的红点内部不展示数字(如下面右图所示)。

由于各厂商对消息角标的实现方案不尽相同,因此只能给他们的手机分别适配处理了。下面就以华为和小米两家的红点方案为例,依次介绍华为系手机(含华为与荣耀品牌)和小米系手机(含小米和红米品牌)的适配编码。 华为的消息角标不依赖通知推送,允许单独设置红点的展示情况,主要通过内容解析器调用华为内核的消息角标服务,详细的角标显示代码示例如下:

代码语言:javascript
复制
    // 华为的消息角标需要事先声明两个权限:INTERNET和CHANGE_BADGE
    private static void showBadgeOfEMUI(Context ctx, int count) {
        try {
            Bundle extra = new Bundle(); // 创建一个包裹对象
            extra.putString("package", BuildConfig.APPLICATION_ID); // 应用的包名
            extra.putString("class", BuildConfig.APPLICATION_ID+".MainActivity"); // 应用的首屏页面路径
            extra.putInt("badgenumber", count); // 应用的消息数量
            Uri uri = Uri.parse("content://com.huawei.android.launcher.settings/badge/");
            // 通过内容解析器调用华为内核的消息角标服务
            ctx.getContentResolver().call(uri, "change_badge", null, extra);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

为了合理使用魔改后的消息角标服务,华为规定要在AndroidManifest.xml中声明两个权限配置,包括互联网权限INTERNET,以及徽章修改权限CHANGE_BADGE,具体的权限配置代码如下所示:

代码语言:javascript
复制
    <!-- 允许访问互联网 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 允许修改徽章(角标数字) -->
    <uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE" />

至于小米的消息角标方案,则依赖于通知推送,必须在发送通知之时一起传送消息数量参数。为此小米给Notification类添加了一个新字段extraNotification,还添加了新方法setMessageCount,前者用于管理桌面上的消息角标,而后者能够设置角标红点的消息数量。下面是在小米手机上显示消息角标的代码例子:

代码语言:javascript
复制
    // 小米的消息角标需要在发送通知的时候一块调用
    private static void showBadgeOfMIUI(int count, Notification notify) {
        try {
            // 利用反射技术获得额外的新增字段extraNotification
            Field field = notify.getClass().getDeclaredField("extraNotification");
            // 该字段为Notification类型,下面获取它的实例对象
            Object extraNotification = field.get(notify);
            // 利用反射技术获得额外的新增方法setMessageCount
            Method method = extraNotification.getClass().getDeclaredMethod("setMessageCount", int.class);
            // 利用反射技术调用实例对象的setMessageCount方法,设置角标红点的消息数量
            method.invoke(extraNotification, count);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

综合上述的两种角标实现方案,形成以下的显示角标代码,可同时兼容华为系手机和小米系手机:

代码语言:javascript
复制
    // 在桌面上的应用图标右上角显示数字角标
    public static void showMarkerCount(Context ctx, int count, Notification notify) {
        showBadgeOfEMUI(ctx, count); // 华为手机EMUI系统的消息角标
        // 小米手机还要进入设置里面的应用管理,开启当前App的“显示桌面图标角标”
        showBadgeOfMIUI(count, notify); // 小米手机MIUI系统的消息角标
    }

不管是华为方案还是小米方案,若想清除桌面上的应用红线,只要调用上面方法设置消息数量为0即可。两种方案的角标效果如下图所示,其中下面左图为华为手机上的消息角标,下面右图为小米手机上的消息角标。

点此查看Android开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档