轻松掌握Notification的各种用法

举报
yechaoa 发表于 2022/05/31 01:05:03 2022/05/31
【摘要】 前言 建议结合代码,看博客更加高效,项目地址: https://github.com/yangchong211/ 通知栏截图 Notification 概述 基础用途概述 Notification,是一种具有全局效果的通知,可以在系统的通知栏中显示。当 APP 向系统发出通知时,它将先以图标的形式显示在通知栏中。用户可以...
前言


建议结合代码,看博客更加高效,项目地址:

https://github.com/yangchong211/

通知栏截图


Notification 概述


基础用途概述

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 完成用户的意图操作)


 Notification 相关分析


常见的用途

  • 显示接收到短消息、及时消息等信息(如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 类。】

流程模块

  1. 创建一个通知栏的Builder构造类  (Create a Notification Builder)

  2. 定义通知栏的Action  (Define the Notification's Action)

  3. 设置通知栏点击事件    (Set the Notification's Click Behavior)

  4. 通知   (Issue the Notification)


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;}
 


Notification 相关属性说明


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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。