前言
这是一个基于 Android 10 源码,全面分析 Android通知系统实现原理 的系列,这是第一篇,全系列将覆盖:
- 1.Notification 的简单使用 和 常用接口介绍
- 2.系统通知服务的启动流程
- 3.通知发送的服务端实现
- 4.通知发送的客户端实现(ing)
- 2.Android 通知系统定制(ing)
写在前面
本篇关注通知的简单使用(发送、更新、删除)和常用接口及其意义,同时会解释两个容易混淆的接口的区别,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,以方便我们设置将要生成的通知的各种属性,下面解释下常用的方法:

这里强调下 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()
接口让我们删除某应用的全部通知。