Android Notification通知详细介绍
目录介绍
- 1.Notification简单概述
- 2.Notification通知用途
- 3.Notification的基本操作
- 3.1 Notification创建必要的属性
- 3.2 Notification简单创建步骤
- 3.3 关于setSmallIcon()与setLargeIcon()区别
- 3.4 Notification的Action属性【交互作用】
- 3.5 更新Notification
- 3.6 取消Notification
- 3.7 设置flag属性
- 3.8 设置Notification的通知效果
- 3.9 设置自定义Notification通知栏布局
- 4.Notification相关属性说明
- 4.1 PendingIntent说明
- 4.2 创建返回栈PendingIntent
- 4.3 注意要点
- 5.部分源码分析思考
- 5.1 RemoteView是什么?
- 5.2 查看源码,了解Notification如何创建布局
- 6.关于其他
- 6.1 参考案例
- 6.2 更新日志
- v1.0 写于2016年6月18日
- v1.1 更新于17年12月6日,重新整理笔记
- 6.3 关于我的博客
0.备注
- 建议结合代码,看博客更加高效,项目地址:https://github.com/yangchong211/YCNotification
- 通知栏截图
-
案例
- 说明及截图
- 模块:新闻,音乐,视频,图片,唐诗宋词,快递,天气,记事本,阅读器等等
- 接口:七牛,阿里云,天行,干货集中营,极速数据,追书神器等等
- 持续更新目录说明
1.Notification简单概述
- Notification,是一种具有全局效果的通知,可以在系统的通知栏中显示。当 APP 向系统发出通知时,它将先以图标的形式显示在通知栏中。用户可以下拉通知栏查看通知的详细信息。通知栏和抽屉式通知栏均是由系统控制,用户可以随时查看。
2.Notification通知用途
- 常见的用途
- 显示接收到短消息、及时消息等信息(如QQ、微信、新浪、短信)
- 显示客户端的推送消息,如广告、优惠、版本更新、推荐新闻等,常用的第三方 SDK 有: JPush 、 个推 、 信鸽 、 网易云信(偏重 IM ) 、 阿里云推送
- 显示正在进行的事物,例如:后台运行的程序,如音乐播放进度、下载进度等
- 前两点可以归结为与用户交互,第三点是实时的任务提醒,但不可否认的是,第三点也会与用户交互。
3.Notification的基本操作
- 3.1 Notification创建必要的属性,必须设置
- 3.1.1 必须添加的属性
- 小图标,通过 setSmallIcon() 方法设置
- 标题,通过 setContentTitle() 方法设置
- 内容,通过 setContentText() 方法设置
- 3.2 Notification创建步骤
- 3.2.1 Notification 的创建主要涉及到 Notification.Builder 、 Notification 、 NotificationManager
Notification.Builer : 使用建造者模式构建 Notification 对象。由于 Notification.Builder 仅支持 Android 4.1及之后的版本,为了解决兼容性问题, Google 在 Android Support v4 中加入了 - NotificationCompat.Builder 类。对于某些在 Android 4.1 之后才特性,即使 NotificationCompat.Builder 支持该方法,在之前的版本中也不能运行。 - Notification : 通知对应类,保存通知相关的数据。- NotificationManager 向系统发送通知时会用到。
- NotificationManager : NotificationManager 是通知管理类,它是一个系统服务。调用 NotificationManager 的 notify() 方法可以向系统发送通知。
- 3.2.2 Notification创建步骤与代码
// 创建一个NotificationManager的引用
NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
// 定义Notification的各种属性
Notification.Builder mBuilder = new Notification.Builder(this.getApplicationContext())
.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI) //
.setSmallIcon(R.mipmap.ic_launcher) //设置通知的图标
.setTicker("有新消息呢") //设置状态栏的标题
.setContentTitle("这个是标题") //设置标题
.setContentText("这个是内容") //消息内容
.setDefaults(Notification.DEFAULT_ALL) //设置默认的提示音
.setPriority(Notification.PRIORITY_DEFAULT) //设置该通知的优先级
.setOngoing(false) //让通知左右滑的时候不能取消通知
.setPriority(Notification.PRIORITY_DEFAULT) //设置该通知的优先级
.setWhen(System.currentTimeMillis()) //设置通知时间,默认为系统发出通知的时间,通常不用设置
.setAutoCancel(true); //打开程序后图标消失
//处理点击Notification的逻辑
Intent resultIntent = new Intent(this, TestActivity.class);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //添加为栈顶Activity
resultIntent.putExtra("what",5);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this,5,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
//发送
mNotificationManager.notify(1, mBuilder.build());
//结束广播
//mNotificationManager.cancel(1);
- 3.3 关于setSmallIcon()与setLargeIcon()区别
- 在 NotificationCompat.Builder 中有设置通知的大小图标的两个方法。这两个方法有什么区别呢?
- 当 setSmallIcon() 与 setLargeIcon() 同时存在时, smallIcon 显示在通知的右下角, largeIcon 显示在左侧
- 当只设置 setSmallIcon() 时, smallIcon 显示在左侧。看下图你就明白了。
- 对于部分 ROM ,可能修改过源码,如 MIUI 上通知的大图标和小图标是没有区别的。
- 效果如图所示:
- 3.4 Notification的Action属性
- 设置一个 Action ,这样就可以直接跳转到 App 的某个 Activity 、启动一个 Service 或者发送一个 Broadcast。否则,Notification 仅仅只能起到通知的效果,而不能与用户交互。
- 具体代码如下所示:
//创建intent
Intent resultIntent = new Intent(this, TestActivity.class);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //添加为栈顶Activity
resultIntent.putExtra("what",5);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this,5,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);
//发送pendingIntent
mBuilder.setContentIntent(resultPendingIntent);
- 3.5 更新Notification
- 更新通知很简单,只需要再次发送相同 ID 的通知即可,如果之前的通知还未被取消,则会直接更新该通知相关的属性;如果之前的通知已经被取消,则会重新创建一个新通知。
更新通知跟发送通知使用相同的方式。
- 3.6 取消Notification
- 取消通知有如下 5 种方式:
- 点击通知栏的清除按钮,会清除所有可清除的通知
- 设置了 setAutoCancel() 或 FLAG_AUTO_CANCEL 的通知,点击该通知时会清除它
- 通过 NotificationManager 调用 cancel(int id) 方法清除指定 ID 的通知
- 通过 NotificationManager 调用 cancel(String tag, int id) 方法清除指定 TAG 和 ID 的通知
- 通过 NotificationManager 调用 cancelAll() 方法清除所有该应用之前发送的通知
- 注意事项
- 如果你是通过 NotificationManager.notify(String tag, int id, Notification notify) 方法创建的通知,那么只能通过 NotificationManager.cancel(String tag, int id) 方法才能清除对应的通知,调用NotificationManager.cancel(int id) 无效。
- 3.7 设置flag属性
- 设置FLAG_NO_CLEAR表示
- 设置通知不能被状态栏的清除按钮给清除掉,也不能被手动清除,但能通过 cancel() 方法清除
- 代码:
private void sendNotification9() {
Notification.Builder mBuilder = new Notification.Builder(this.getApplicationContext())
.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI)
.setSmallIcon(R.mipmap.ic_launcher) //设置通知的图标
.setTicker("有新消息呢9") //设置状态栏的标题
.setContentTitle("这个是标题9") //设置标题
.setContentText("这个是内容9") //消息内容
.setDefaults(Notification.DEFAULT_ALL) //设置默认的提示音
.setOngoing(false) //让通知左右滑的时候不能取消通知
.setAutoCancel(true); //打开程序后图标消失
Notification notification = mBuilder.build();
//设置 Notification 的 flags = FLAG_NO_CLEAR
//FLAG_NO_CLEAR 表示该通知不能被状态栏的清除按钮给清除掉,也不能被手动清除,但能通过 cancel() 方法清除
//flags 可以通过 |= 运算叠加效果
notification.flags |= Notification.FLAG_NO_CLEAR;
//获取NotificationManager 对象
mNotificationManager.notify(9, notification);
}
//取消通知:
if(mNotificationManager!=null){
mNotificationManager.cancelAll();
}
- 3.8 设置Notification的通知效果
- Notification 有震动、响铃、呼吸灯三种响铃效果,可以通过 setDefaults(int defualts) 方法来设置。 Default 属性有以下四种,一旦设置了 Default 效果,自定义的效果就会失效。楼主在这里踩了坑,愣是调了半天没找到为什么自定义效果会消失,忘大家慎之。
//设置系统默认提醒效果,一旦设置默认提醒效果,则自定义的提醒效果会全部失效。具体可看源码//添加默认震动效果,需要申请震动权限//<uses-permission android:name="android.permission.VIBRATE" />
Notification.DEFAULT_VIBRATE
//添加系统默认声音效果,设置此值后,调用setSound()设置自定义声音无效
Notification.DEFAULT_SOUND
//添加默认呼吸灯效果,使用时须与 Notification.FLAG_SHOW_LIGHTS 结合使用,否则无效
Notification.DEFAULT_LIGHTS
//添加上述三种默认提醒效果
Notification.DEFAULT_ALL
- 除了以上几种设置 Notification 默认通知效果,还可以通过以下几种 FLAG 设置通知效果。
//提醒效果常用 Flag//三色灯提醒,在使用三色灯提醒时候必须加该标志符
Notification.FLAG_SHOW_LIGHTS
//发起正在运行事件(活动中)
Notification.FLAG_ONGOING_EVENT
//让声音、振动无限循环,直到用户响应 (取消或者打开)
Notification.FLAG_INSISTENT
//发起Notification后,铃声和震动均只执行一次
Notification.FLAG_ONLY_ALERT_ONCE
//用户单击通知后自动消失
Notification.FLAG_AUTO_CANCEL
//只有调用NotificationManager.cancel()时才会清除
Notification.FLAG_NO_CLEAR
//表示正在运行的服务
Notification.FLAG_FOREGROUND_SERVICE
- 设置默认提醒
// 添加默认声音提醒
builder.setDefaults(Notification.DEFAULT_SOUND);
// 添加默认呼吸灯提醒,自动添加FLAG_SHOW_LIGHTS
builder.setDefaults(Notification.DEFAULT_LIGHTS);
- 设置铃声属性,用的很少
private void sendNotification11() {
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("我是伴有铃声效果的通知11")
.setContentText("美妙么?安静听~11")
//调用系统默认响铃,设置此属性后setSound()会无效
//.setDefaults(Notification.DEFAULT_SOUND)
//调用系统多媒体裤内的铃声
//.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2"));
//调用自己提供的铃声,位于 /res/values/raw 目录下
.setSound(Uri.parse("android.resource://com.yc.cn.ycnotification/" + R.raw.hah));
//另一种设置铃声的方法
//Notification notify = builder.build();
//调用系统默认铃声
//notify.defaults = Notification.DEFAULT_SOUND;
//调用自己提供的铃声
//notify.sound = Uri.parse("android.resource://com.yc.cn.ycnotification/"+R.raw.sound);
//调用系统自带的铃声
//notify.sound = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2");
//mManager.notify(11,notify);
mNotificationManager.notify(11, builder.build());
}
- 设置震动属性
private void sendNotification12() {
//震动也有两种设置方法,与设置铃声一样,在此不再赘述
long[] vibrate = new long[]{0, 500, 1000, 1500};
Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("我是伴有震动效果的通知")
.setContentText("颤抖吧,逗比哈哈哈哈哈~")
//使用系统默认的震动参数,会与自定义的冲突
//.setDefaults(Notification.DEFAULT_VIBRATE)
//自定义震动效果
.setVibrate(vibrate);
//另一种设置震动的方法
//Notification notify = builder.build();
//调用系统默认震动
//notify.defaults = Notification.DEFAULT_VIBRATE;
//调用自己设置的震动
//notify.vibrate = vibrate;
//mManager.notify(3,notify);
mNotificationManager.notify(12, builder.build());
}
- 3.9 设置自定义Notification通知栏布局
- 代码如下,注意,这里只取部分代码,完整代码可以下载github的完整项目:https://github.com/yangchong211/YCNotification
.setContent(getRemoteViews()) // 设置通知栏的布局
//创建自定义布局
private RemoteViews getRemoteViews() {
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_mobile_play);
// 设置 点击通知栏的上一首按钮时要执行的意图
remoteViews.setOnClickPendingIntent(R.id.btn_pre, getActivityPendingIntent(11));
// 设置 点击通知栏的下一首按钮时要执行的意图
remoteViews.setOnClickPendingIntent(R.id.btn_next, getActivityPendingIntent(12));
// 设置 点击通知栏的播放暂停按钮时要执行的意图
remoteViews.setOnClickPendingIntent(R.id.btn_start, getActivityPendingIntent(13));
// 设置 点击通知栏的根容器时要执行的意图
remoteViews.setOnClickPendingIntent(R.id.ll_root, getActivityPendingIntent(14));
remoteViews.setTextViewText(R.id.tv_title, "标题"); // 设置通知栏上标题
remoteViews.setTextViewText(R.id.tv_artist, "艺术家"); // 设置通知栏上艺术家
return remoteViews;
}
4.Notification相关属性说明
- 4.1 PendingIntent说明
- 4.1.1 PendingIntent基本说明
- PendingIntent 是一种特殊的 Intent ,字面意思可以解释为延迟的 Intent ,用于在某个事件结束后执行特定的 Action 。从上面带 Action 的通知也能验证这一点,当用户点击通知时,才会执行。
- PendingIntent 是 Android 系统管理并持有的用于描述和获取原始数据的对象的标志(引用)。也就是说,即便创建该PendingIntent对象的进程被杀死了,这个PendingItent对象在其他进程中还是可用的。
日常使用中的短信、闹钟等都用到了 PendingIntent。
- 4.1.2 PendingIntent三种获取方式
//获取一个用于启动 Activity 的 PendingIntent 对象public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags);
//获取一个用于启动 Service 的 PendingIntent 对象public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags);
//获取一个用于向 BroadcastReceiver 广播的 PendingIntent 对象public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
- 4.1.3 PendingIntent具有几种flag
FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的 PendingIntent 对象,那么就将先将已有的 PendingIntent 取消,然后重新生成一个 PendingIntent 对象。
FLAG_NO_CREATE:如果当前系统中不存在相同的 PendingIntent 对象,系统将不会创建该 PendingIntent 对象而是直接返回 null 。
FLAG_ONE_SHOT:该 PendingIntent 只作用一次。
FLAG_UPDATE_CURRENT:如果系统中已存在该 PendingIntent 对象,那么系统将保留该 PendingIntent 对象,但是会使用新的 Intent 来更新之前 PendingIntent 中的 Intent 对象数据,例如更新 Intent 中的 Extras 。
- 4.2 创建返回栈PendingIntent
- 4.2.1 添加返回栈代码
默认情况下,从通知启动一个Activity,按返回键会回到主屏幕。
但某些时候有按返回键仍然留在当前应用的需求,这就要用到TaskStackBuilder了。
Notification.Builder mBuilder = new Notification.Builder(context)
.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("广播接受者标题,小杨")
.setContentText("广播接受者内容,扯犊子")
.setAutoCancel(true);
Log.i(TAG, "onReceive: intent" + intent.getClass().getName());
Intent resultIntent = new Intent(context, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
//将该Activity添加为栈顶
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
- 4.3 注意要点
- 如果用户的手机使静音模式,那么设置铃声或者震动效果将会失效
5.部分源码分析思考
- 5.1 RemoteView是什么?
- 5.1.1 什么是RemoteView?
- 为啥Notification不会设计成和普通View一样的使用方式?理由很简单!状态栏不是单单由你的应用程序管理.状态栏是由Android系统管理的.你需要显示Notification就必须和系统打交道.必须通过Notification服务才能显示你的Notification.所以设计成用一个Notification实例代表一个Notification,然后通过notificationManager.notify函数提交给Notification服务.
- 5.1.2 Notification服务是什么?是一个独立的线程!
- 又扯出一个问题.跨线程显示View.该怎么显示?不是在本应用程序显示View.这里就要借用RemoteView.
- RemoteView理解成对一个View的封装,然后把RemoteView提交给其他线程.其他线程接收到RemoteView并且解析里面View的信息把它显示出来.
- 5.1.3 在使用系统自带的Notification系统会创建一个默认的RemoteView!
- 系统默认使用R.layout.notification_template_material_base生产一个RemoteView.
至于这里的布局是怎么查到的,请看下面源码分析
- 5.2 查看源码,了解Notification如何创建布局
- 5.2.1 首先看Notification中build代码
- 5.2.2 然后看上图中的createContentView()方法
- 5.2.3 然后看上图中的createContentView()方法
时间: 2024-10-23 22:35:20