轻松掌握Notification的各种用法
建议结合代码,看博客更加高效,项目地址:
https://github.com/yangchong211/
通知栏截图
基础用途概述
Notification,是一种具有全局效果的通知,可以在系统的通知栏中显示。当 APP 向系统发出通知时,它将先以图标的形式显示在通知栏中。用户可以下拉通知栏查看通知的详细信息。通知栏和抽屉式通知栏均是由系统控制,用户可以随时查看。
通知栏思维导图结构
Notificaiton -- service -- BroadcastReceiver -- Intent(flag、Action 等属性应用) -- PendingIntent
一个 Notificaiton 通知的拓展使用就要涉及与4大组建的配合,所以要学好整体的知识体系。
通知与四大组件有什么联系呢?
比如音乐播放器中,后台播放音乐,由于 service 是在后台运行,所以意图做什么我们看不到,这个时候可以通过 Notificaiton 来显示提醒。具体案例可以参考我的音乐播放器:
https://github.com/yangchong211/YCVideoPlayer
同样,在音乐播放器中,程序在后台运行,点击音乐播放器的通知栏上的上一曲,下一曲等,那么可以让 service 服务和 BroadcastReceiver 广播相结合
Intent 作为意图处理,和 Notificaiton 的点击时间紧密结合在了一起,并且与 BroadcastReceiver 和 service 的联系也紧密不可以分割。
(service 在后台之后通过 BroadcastReceiver 来通知 Notificaiton 显示相关东西,在通过 Intent 完成用户的意图操作)
常见的用途
显示接收到短消息、及时消息等信息(如QQ、微信、新浪、短信)
显示客户端的推送消息,如广告、优惠、版本更新、推荐新闻等,常用的第三方 SDK 有: JPush 、 个推 、 信鸽 、 网易云信(偏重 IM ) 、 阿里云推送
显示正在进行的事物,例如:后台运行的程序,如音乐播放进度、下载进度等
前两点可以归结为与用户交互,第三点是实时的任务提醒,但不可否认的是,第三点也会与用户交互。
对应的官方文档
官方
http://developer.android.com/design/patterns/notifications.html
使用教程
http://developer.android.com/training/notify-user/index.html
开发文档
http://developer.android.com/reference/android/app/Notification.html
通知栏主要的类:Notification 和 NotificationManager
NotificationManager : 是状态栏通知的管理类,负责发通知、清除通知等操作。
Notification 为通知信息类,它里面对应了通知栏的各个属性【备注:使用建造者模式构建 Notification 对象。由于 Notification.Builder 仅支持 Android 4.1及之后的版本,为了解决兼容性问题, Google 在 Android Support v4 中加入了 NotificationCompat.Builder 类。】
流程模块
创建一个通知栏的Builder构造类 (Create a Notification Builder)
定义通知栏的Action (Define the Notification's Action)
设置通知栏点击事件 (Set the Notification's Click Behavior)
通知 (Issue the Notification)
Notification创建必要的属性,必须添加的属性
小图标,通过 setSmallIcon() 方法设置
标题,通过 setContentTitle() 方法设置
内容,通过 setContentText() 方法设置
Notification 创建步骤
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 的 notify() 方法可以向系统发送通知。
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); //添加为栈顶ActivityresultIntent.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);
关于 setSmallIcon() 与 setLargeIcon() 区别
在 NotificationCompat.Builder 中有设置通知的大小图标的两个方法。这两个方法有什么区别呢?
当 setSmallIcon() 与 setLargeIcon() 同时存在时, smallIcon 显示在通知的右下角, largeIcon 显示在左侧
当只设置 setSmallIcon() 时, smallIcon 显示在左侧。
对于部分 ROM ,可能修改过源码,如 MIUI 上通知的大图标和小图标是没有区别的。
Notification 的 Action 属性
设置一个 Action ,这样就可以直接跳转到 App 的某个 Activity 、启动一个 Service 或者发送一个 Broadcast。否则,Notification 仅仅只能起到通知的效果,而不能与用户交互。
具体代码如下所示:
//创建intentIntent resultIntent = new Intent(this, TestActivity.class);resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //添加为栈顶ActivityresultIntent.putExtra("what",5);PendingIntent resultPendingIntent = PendingIntent.getActivity(this,5,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);//发送pendingIntentmBuilder.setContentIntent(resultPendingIntent);
更新 Notification
更新通知很简单,只需要再次发送相同 ID 的通知即可,如果之前的通知还未被取消,则会直接更新该通知相关的属性;如果之前的通知已经被取消,则会重新创建一个新通知。
更新通知跟发送通知使用相同的方式。
取消 Notification
点击通知栏的清除按钮,会清除所有可清除的通知
设置了 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) 无效。
设置 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();}
设置 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 默认通知效果,还可以通过以下几种 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_LIGHTSbuilder.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());}
设置自定义 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;}
PendingIntent 说明
PendingIntent 基本说明
PendingIntent 和 Intent 略有不同,它可以设置执行次数,主要用于远程服务通信、闹铃、通知、启动器、短信中,在一般情况下用的比较少。
PendingIntent 是一种特殊的 Intent ,字面意思可以解释为延迟的 Intent ,用于在某个事件结束后执行特定的 Action 。从上面带 Action 的通知也能验证这一点,当用户点击通知时,才会执行。
PendingIntent 是 Android 系统管理并持有的用于描述和获取原始数据的对象的标志(引用)。也就是说,即便创建该 PendingIntent 对象的进程被杀死了,这个 PendingItent 对象在其他进程中还是可用的。
日常使用中的短信、闹钟等都用到了 PendingIntent。
PendingIntent 相关属性 flag
PendingIntent的位标识符:
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 。
PendingIntent 三种获取方式
它支持多种相应方式,有Activity、Broadcast、Service,根据你自身需求去选择。
//获取一个用于启动 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)
创建返回栈 PendingIntent
添加返回栈代码
默认情况下,从通知启动一个 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());
注意要点
如果用户的手机使静音模式,那么设置铃声或者震动效果将会失效。
RemoteView是什么?
为啥 Notification 不会设计成和普通 View 一样的使用方式?理由很简单!状态栏不是单单由你的应用程序管理。状态栏是由 Android 系统管理的。你需要显示 Notification 就必须和系统打交道。必须通过 Notification 服务才能显示你的 Notification。所以设计成用一个 Notification 实例代表一个 Notification,然后通过 notificationManager.notify 函数提交给 Notification 服务。Notification 服务是什么?是一个独立的线程!
又扯出一个问题:跨线程显示 View,该怎么显示?不是在本应用程序显示 View。这里就要借用 RemoteView.
RemoteView 理解成对一个 View 的封装,然后把 RemoteView 提交给其他线程。其他线程接收到 RemoteView 并且解析里面 View 的信息把它显示出来.
在使用系统自带的 Notification 系统会创建一个默认的 RemoteView !
系统默认使用 R.layout.notification_template_material_base生 产一个 RemoteView。
Notification 如何创建布局
Notification 中 build 代码:
上图中的 createContentView() 方法
接着进入 getBaseLayoutResource()
这样,我们就大致地了解了整个流程。
原文地址:https://mp.weixin.qq.com/s/2TaWICQ4nWV3TuPG71CBGw
文章来源: blog.csdn.net,作者:yechaoa,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/yechaoa/article/details/79719153
- 点赞
- 收藏
- 关注作者
评论(0)