Notification 的简单使用 和 常用接口介绍

2,625 阅读4分钟

前言

这是一个基于 Android 10 源码,全面分析 Android通知系统实现原理 的系列,这是第一篇,全系列将覆盖:

写在前面

本篇关注通知的简单使用(发送、更新、删除)和常用接口及其意义,同时会解释两个容易混淆的接口的区别,setSmallIcon 和 setLargeIcon ,以及发送通知时传入的tag、id参数的用途。

附上 Google Notification 官方文档,包含了各种类型通知的 使用说明 和 使用注意项,本系列是剖析 Android通知系统实现原理,不会在使用上做过多说明。

Notification 的简单使用 和 常用接口介绍

来看看如何发送一条通知:

    private void sendNoti(){
        final String CHANNEL_ID = "demo_channel_id";
        final String CHANNEL_NAME = "demo_channel_name";
        final String CHANNEL_DESCRIPTION = "demo_channel_des";
        final CharSequence title = "title";
        final CharSequence content = "content";
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        // 步骤1:告诉 Notification.Builder 我们需要的通知内容
        final Notification.Builder builder = new Notification.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher_round)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setContentTitle(title)
                .setContentText(content)
                .setWhen(System.currentTimeMillis())
                .setContentIntent(contentPendingIntent)
                .setDeleteIntent(deletePendingIntent)
                .addAction(action);
        // 步骤2:Android 8.0 新增了 NotificationChannel,这里需要做版本区分
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
            mChannel.setDescription(CHANNEL_DESCRIPTION);
            notificationManager.createNotificationChannel(mChannel);
            builder.setChannelId(CHANNEL_ID);
        }
        // 步骤3:拿到我们前面让 Notification.Builder 去帮忙构建的通知
        Notification notification =  builder.build();
        // 步骤4:调用 NotificationManager.notify() 发送通知
        notificationManager.notify(notiTag, notiId, notification);
    }

总结一下 通知的使用流程 就是:

  • 1.使用 Notification.Builder构建通知
  • 2.根据 Android 版本决定是否设置 Channel
  • 3.构建完成后调用 Notification.Builder.build(); 获取通知
  • 4.调用 NotificationManager.notify() 发送通知

可以看到使用是十分简单的,下面对这几个步骤展开说明一下:

1.Notification 类基于 建造者模式,提供了一个静态内部类 Builder,以方便我们设置将要生成的通知的各种属性,下面解释下常用的方法:

常用Builder方法及其意义解释.png

这里强调下 setSmallIcon() 与 setLargeIcon() 的区别:

  • 当开发者未设置 largeIcon 时,系统将在通知内容的左侧显示 smallIcon;
  • 当开发者设置了 largeIcon 时,系统会将指定资源覆盖在 原通知内容左侧的 smallIcon 区域;
  • 目前国内各大厂商基本都定制了自己的通知模板,也就是最终 通知内容中的 smallIcon、largeIcon 显示与否以及显示位置都受厂商定制影响。

2.下面看看通知的发送、更新、删除等操作:

2.1 通知发送:

通知发送的入口是:NotificationManager.notify() / notifyAsUser()函数,其中notify()有两个重载方法:

/*frameworks/base/core/java/android/app/NotificationManager.java*/
    public void notify(int id, Notification notification)
    {
        notify(null, id, notification);
    }

    public void notify(String tag, int id, Notification notification)
    {
        notifyAsUser(tag, id, notification, mContext.getUser());
    }

    public void notifyAsUser(String tag, int id, Notification notification, UserHandle user) {......}

最终调用的都是notifyAsUser(String tag, int id, Notification notification, UserHandle user)这个方法,可以看到 id 和 notification 是最基本的参数,不可为空,tag 和 user 可为空,当我们不传入这两个参数时,系统会默认补充 tag = null 和 user = Context.getUser(),先说明下这几个参数:

  • **tag:**通知的tag,用以和 id 组合 (tag, id), 以便唯一标识 某应用内的某条通知,对开发者而言,该参数在后续更新和取消通知时会有用
  • **id:**通知的 id,用以和 tag 组合 (tag, id), 以便唯一标识 某应用内的某条通知,对开发者而言,该参数在后续更新和取消通知时会有用
  • **notification:**前面通过 Notification.Builder 构建出来的通知
  • **user:**现在的手机一般都支持多用户,自然而然的通知应该是跟随用户的,所以我们可以通过该参数来标识当前用户

2.2 通知更新:

有些时候我们发送完通知后,需要对通知的内容进行更新,例如替换图标资源、文字资源等,这个时候就需要对通知进行更新,通知的更新调用的也是 notify 方法,假定我们前面已经通过 notify(tag, id, notification) 发送了一条通知,现在我们希望更新该通知,那么我们可以重新构建一个 Notification 对象,然后再次调用 notify(tag, id, notification),传入一样的tag、id ,便能实现更新通知的目的了,常见的场景包括 下载中的通知,音乐播放器的通知 等。

2.3 通知删除:

NotificationManager 提供了多个删除通知的接口:

/*frameworks/base/core/java/android/app/NotificationManager.java*/
    public void cancel(int id)
    {
        cancel(null, id);
    }

    public void cancel(String tag, int id)
    {
        cancelAsUser(tag, id, mContext.getUser());
    }

    public void cancelAsUser(String tag, int id, UserHandle user) {......}
  
    public void cancelAll() {......}

可以看到,删除通知依旧需要用到我们前面将的 tag、id,这个很好理解,就不多解释了,注意 NotificationManager 还提供了一个 cancelAll() 接口让我们删除某应用的全部通知。