适用Android系统:

1) Android版本>= 5.0

2) 部分ROM是不支持

 RemoteViews view=getRemoteViews(body,title, R.mipmap.ic_report_problem_red_24px, 0, date);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.L){
notification.headsUpContentView=view;
notification.vibrate= new long[]{ 100 };
notification.visibility = Notification.VISIBILITY_PUBLIC;
}
notification.contentView = view;

views : 自己赋值的RemoteViews,建议高度适用64dp,因为高度高了,有可能会出现截断(系统做处理)。

notification.visibility =  Notification.VISIBILITY_PUBLIC (在锁屏界面展示,具体赋值类型,请参考Notification)。

什么是通知(Notification)

通知是一个可以在应用程序正常的用户界面之外显示给用户的消息。
通知发出时,它首先出现在状态栏的通知区域中,用户打开通知抽屉可查看通知详情。通知区域和通知抽屉都是用户可以随时查看的系统控制区域。

作为安卓用户界面的重要组成部分,通知有自己的设计指南。在Android 5.0(API level 21)中引入的 Material Design 的变化是特别重要的,更多信息请阅读 通知设计指南

如何创建通知

随着Android系统不断升级,Notification的创建方式也随之变化,主要变化如下:

Android 3.0之前

Android 3.0 (API level 11)之前,使用new Notification()方式创建通知:

NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ResultActivity.class), 0); Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(this, title, content, contentIntent); mNotifyMgr.notify(NOTIFICATIONS_ID, notification);

Android 3.0 (API level 11)及更高版本

Android 3.0开始弃用new Notification()方式,改用Notification.Builder()来创建通知:

NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ResultActivity.class), 0); Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setContentIntent(contentIntent)
.build(); // getNotification() deprecated in API level 16 mNotifyMgr.notify(NOTIFICATIONS_ID, notification);

这里需要注意: “build()” 是Androdi 4.1(API level 16)加入的,用以替代”getNotification()”。API level 16开始弃用”getNotification()”

兼容Android 3.0之前的版本

为了兼容API level 11之前的版本,v4 Support Library中提供了NotificationCompat.Builder()这个替代方法。它与Notification.Builder()类似,二者没有太大区别。

NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ResultActivity.class), 0); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setContentIntent(contentIntent); mNotifyMgr.notify(NOTIFICATIONS_ID, mBuilder.build());

注:除特别说明外,本文将根据 NotificationCompat.Builder() 展开解析,Notification.Builder()类似。

通知基本用法

通知的必要属性

一个通知必须包含以下三项属性:

  • 小图标,对应 setSmallIcon()
  • 通知标题,对应 setContentTitle()
  • 详细信息,对应 setContentText()

其他属性均为可选项,更多属性方法请参考NotificationCompat.Builder

尽管其他都是可选的,但一般都会为通知添加至少一个动作(Action),这个动作可以是跳转到Activity、启动一个Service或发送一个Broadcas等。 通过以下方式为通知添加动作:

  • 使用PendingIntent
  • 通过大视图通知的 Action Button //仅支持Android 4.1 (API level 16)及更高版本,稍后会介绍

创建通知

1、实例化一个NotificationCompat.Builder对象

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");

NotificationCompat.Builder自动设置的默认值:

  • priority: PRIORITY_DEFAULT
  • when: System.currentTimeMillis()
  • audio stream: STREAM_DEFAULT

2、定义并设置一个通知动作(Action)

Intent resultIntent = new Intent(this, ResultActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(
this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);

3、生成Notification对象

Notificatioin notification = mBuilder.build();

4、使用NotificationManager发送通知

// Sets an ID for the notification
int mNotificationId = 001; // Gets an instance of the NotificationManager service
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // Builds the notification and issues it.
mNotifyMgr.notify(mNotificationId, notification);

更新通知

更新通知很简单,只需再次发送相同ID的通知即可,如果之前的通知依然存在则会更新通知属性,如果之前通知不存在则重新创建。
示例代码:

NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status); int numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
mNotifyBuilder.setContentText("new content text")
.setNumber(++numMessages);
// Because the ID remains unchanged, the existing notification is updated.
mNotifyMgr.notify(notifyID, mNotifyBuilder.build());
...

取消通知

取消通知有如下4种方式:

  • 点击通知栏的清除按钮,会清除所有可清除的通知
  • 设置了 setAutoCancel() 或 FLAG_AUTO_CANCEL的通知,点击该通知时会清除它
  • 通过 NotificationManager 调用 cancel() 方法清除指定ID的通知
  • 通过 NotificationManager 调用 cancelAll() 方法清除所有该应用之前发送的通知

通知类型

大视图通知

通知有两种视图:普通视图和大视图。
普通视图:

大视图:

默认情况下为普通视图,可通过NotificationCompat.Builder.setStyle()设置大视图。

注: 大视图(Big Views)由Android 4.1(API level 16)开始引入,且仅支持Android 4.1及更高版本。

构建大视图通知

以上图为例:
1、构建Action Button的PendingIntent

Intent dismissIntent = new Intent(this, PingService.class);
dismissIntent.setAction(CommonConstants.ACTION_DISMISS);
PendingIntent piDismiss = PendingIntent.getService(this, 0, dismissIntent, 0); Intent snoozeIntent = new Intent(this, PingService.class);
snoozeIntent.setAction(CommonConstants.ACTION_SNOOZE);
PendingIntent piSnooze = PendingIntent.getService(this, 0, snoozeIntent, 0);

2、构建NotificatonCompat.Builder对象

NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(getString(R.string.notification))
.setContentText(getString(R.string.ping))
.setDefaults(Notification.DEFAULT_ALL) // requires VIBRATE permission
// 该方法在Android 4.1之前会被忽略
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
//添加Action Button
.addAction (R.drawable.ic_stat_dismiss,
getString(R.string.dismiss), piDismiss)
.addAction (R.drawable.ic_stat_snooze,
getString(R.string.snooze), piSnooze);

3、其他步骤与普通视图相同

进度条通知

  • 明确进度的进度条
    使用setProgress(max, progress, false)来更新进度。
    max: 最大进度值
    progress: 当前进度
    false: 是否是不明确的进度条

    模拟下载过程,示例如下:

        int id = 1;
    ...
    mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mBuilder = new NotificationCompat.Builder(this);
    mBuilder.setContentTitle("Picture Download")
    .setContentText("Download in progress")
    .setSmallIcon(R.drawable.ic_notification); // Start a lengthy operation in a background thread
    new Thread(
    new Runnable() {
    @Override
    public void run() {
    int incr;
    for (incr = 0; incr <= 100; incr+=5) {
    mBuilder.setProgress(100, incr, false);
    mNotifyManager.notify(id, mBuilder.build());
    try {
    // Sleep for 5 seconds
    Thread.sleep(5*1000);
    } catch (InterruptedException e) {
    Log.d(TAG, "sleep failure");
    }
    }
    mBuilder.setContentText("Download complete")//下载完成
    .setProgress(0,0,false); //移除进度条
    mNotifyManager.notify(id, mBuilder.build());
    }
    }
    ).start();


    上图,分别为下载过程中进度条通知 和 下载完成移除进度条后的通知。

  • 不确定进度的进度条
    使用setProgress(0, 0, true)来表示进度不明确的进度条

    mBuilder.setProgress(0, 0, true); mNotifyManager.notify(id, mBuilder.build());

浮动通知(Heads-up Notifications)

Android 5.0(API level 21)开始,当屏幕未上锁且亮屏时,通知可以以小窗口形式显示。用户可以在不离开当前应用前提下操作该通知。
如图:

NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status)
.setFullScreenIntent(pendingIntent, false);

以下两种情况会显示浮动通知:

  • setFullScreenIntent(),如上述示例。
  • 通知拥有高优先级且使用了铃声和振动

锁屏通知

Android 5.0(API level 21)开始,通知可以显示在锁屏上。用户可以通过设置选择是否允许敏感的通知内容显示在安全的锁屏上。
你的应用可以通过setVisibility()控制通知的显示等级:

  • VISIBILITY_PRIVATE : 显示基本信息,如通知的图标,但隐藏通知的全部内容
  • VISIBILITY_PUBLIC : 显示通知的全部内容
  • VISIBILITY_SECRET : 不显示任何内容,包括图标

自定义通知

Android系统允许使用RemoteViews来自定义通知。
自定义普通视图通知高度限制为64dp,大视图通知高度限制为256dp。同时,建议自定义通知尽量简单,以提高兼容性。

自定义通知需要做如下操作:
1、创建自定义通知布局
2、使用RemoteViews定义通知组件,如图标、文字等
3、调用setContent()将RemoteViews对象绑定到NotificationCompat.Builder
4、同正常发送通知流程

注意: 避免为通知设置背景,因为兼容性原因,有些文字可能看不清。

定义通知文本样式

通知的背景颜色在不同的设备和版本中有所不同,Android2.3开始,系统定义了一套标准通知文本样式,建议自定义通知使用标准样式,这样有助于通知文本可见。
通知文本样式:

Android 5.0之前可用:
android:style/TextAppearance.StatusBar.EventContent.Title // 通知标题样式
android:style/TextAppearance.StatusBar.EventContent // 通知内容样式 Android 5.0及更高版本:
android:style/TextAppearance.Material.Notification.Title // 通知标题样式
android:style/TextAppearance.Material.Notification // 通知内容样式

更多通知的标准样式和布局,可参考源码frameworks/base/core/res/res/layout路径下的通知模版如:

Android 5.0之前:
notification_template_base.xml
notification_template_big_base.xml
notification_template_big_picture.xml
notification_template_big_text.xml Android 5.0 及更高版本:
notification_template_material_base.xml
notification_template_material_big_base.xml
notification_template_material_big_picture.xml
notification_template_part_chronometer.xml
notification_template_progressbar.xml 等等。

保留Activity返回栈

常规Activity

默认情况下,从通知启动一个Activity,按返回键会回到主屏幕。但某些时候有按返回键仍然留在当前应用的需求,这就要用到TaskStackBuilder了。

1、在manifest中定义Activity的关系

Android 4.0.3 及更早版本
<activity
android:name=".ResultActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>


Android 4.1 及更高版本
<activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity">
</activity>

2、创建返回栈PendingIntent

Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// 添加返回栈
stackBuilder.addParentStack(ResultActivity.class);
// 添加Intent到栈顶
stackBuilder.addNextIntent(resultIntent);
// 创建包含返回栈的pendingIntent
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
上述操作后,从通知启动ResultActivity,按返回键会回到MainActivity,而不是主屏幕。

特殊Activity

默认情况下,从通知启动的Activity会在近期任务列表里出现。如果不需要在近期任务里显示,则需要做以下操作:

1、在manifest中定义Activity

<activity
android:name=".ResultActivity"
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true">
</activity>

2、构建PendingIntent

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
Intent notifyIntent = new Intent(this, ResultActivity.class); // Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); PendingIntent notifyPendingIntent =
PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(notifyPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());

上述操作后,从通知启动ResultActivity,此Activity不会出现在近期任务列表中。

通知常见属性和常量

通知的提醒方式

1、声音提醒

  • 默认声音
    notification.defaults |= Notification.DEFAULT_SOUND;

  • 自定义声音
    notification.sound = Uri.parse(“file:///sdcard0/notification.ogg”);

2、震动提醒

  • 默认振动
    notification.defaults |= Notification.DEFAULT_VIBRATE;

  • 自定义振动
    long[] vibrate = {100, 200, 300, 400}; //震动效果
    // 表示在100、200、300、400这些时间点交替启动和关闭震动 notification.vibrate = vibrate;

3、闪烁提醒

  • 默认闪烁
    notification.defaults |= Notification.DEFAULT_LIGHTS;

  • 自定义闪烁
    notification.ledARGB = 0xff00ff00; // LED灯的颜色,绿灯
    notification.ledOnMS = 300; // LED灯显示的毫秒数,300毫秒
    notification.ledOffMS = 1000; // LED灯关闭的毫秒数,1000毫秒
    notification.flags |= Notification.FLAG_SHOW_LIGHTS; // 必须加上这个标志

常见的Flags

  • FLAG_AUTO_CANCEL
    当通知被用户点击之后会自动被清除(cancel)

  • FLAG_INSISTENT
    在用户响应之前会一直重复提醒音

  • FLAG_ONGOING_EVENT
    表示正在运行的事件

  • FLAG_NO_CLEAR
    通知栏点击“清除”按钮时,该通知将不会被清除

  • FLAG_FOREGROUND_SERVICE
    表示当前服务是前台服务

更多Notification属性详见Notification

Android 5.0以上heads up通知的更多相关文章

  1. 在 Xamarin.Android 中使用 Notification.Builder 构建通知

    0 背景 在 Android 4.0 以后,系统支持一种更先进的 Notification.Builder 类来发送通知.但 Xamarin 文档含糊其辞,多方搜索无果,遂决定自己摸索. 之前的代码: ...

  2. Android 8.0+ 通知不显示的适配

    最近在 写项目的时候  发现 通知并不会显示的问题,查看资料发现 从Android 8.0开始通知必须加上ChannelId Android O 引入了 通知渠道(Notification Chann ...

  3. 对Android 8.0以上版本通知点击无效的一次分析

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/178 对Android 8.0以上版本通知点击无效的一次分 ...

  4. Android 7.0 Nougat牛轧糖 发布啦

    Android 7.0 Nougat牛轧糖 发布啦 Android 7.0 Nougat 牛轧糖于本月发布了. 从官方blog里可以了解到这个版本的新特性. Android 7.0 从2016年8月正 ...

  5. Android 6.0 - 动态权限管理的解决方案

    Android 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应 ...

  6. 有史来最大改变 Android 5.0十大新特性

    有史来最大改变 Android 5.0十大新特性 2014.10.16 14:51:31 来源:腾讯数码作者:腾讯数码 ( 0 条评论 )   距离Android系统上一次重大更新不到一年的时间,谷歌 ...

  7. 【译】Android 6.0 Changes (机翻加轻微人工校对)

    Android 6.0 Changes In this document Runtime Permissions Doze and App Standby Apache HTTP Client Rem ...

  8. 谈谈Android 6.0运行时权限理解

    前言 谷歌在2015年8月份时候,发布了Android 6.0版本,代号叫做“棉花糖”(Marshmallow ),其中的很大的一部分变化,是在用户权限授权上,或许是感觉之前默认授权的不合理,现在6. ...

  9. Android 6.0 新功能及主要 API 变更

    运行时权限 这个版本中引入了新的权限模型,现在用户可以在运行时直接管理应用程序的权限.这个模型基于用户对权限控制的更多可见性,同时为应用程序的开发者提供更流畅的应用安装和自动升级.用户可以为已安装的每 ...

随机推荐

  1. Git 之 与Github交互

    我们不可能只在一台电脑上开发,白天在公司用公司电脑,晚上在家可以用自己电脑.但是这个代码怎么让两台电脑同步呢?总不能用U盘复制粘贴.太繁琐. 这里我们就可以找个代码托管的平台,帮我们做这件事. Git ...

  2. 数据库commit问题

    对数据库进行修改后,需要commit!---之前也是忘记commit导致数据库反应不过来.

  3. JDBC方式从数据库中查询数据并显示

    1.创建数据库表myuser DROP TABLE IF EXISTS `myuser`; CREATE TABLE `myuser` ( `) NOT NULL COMMENT '姓名', `id` ...

  4. Visual Studio2012快捷键总结

    (1)如何设置更改快捷键 1.进入工具----选项  对话框 2.选择  环境---->键盘 3.在 [显示命令包含] 下面的对话框中输入“对齐”关键字,然后就会在这个编辑框下面一个文本窗口中显 ...

  5. Picasso VS Glide

    原文: Introduction to Glide, Image Loader Library for Android, recommended by Google 在泰国举行的谷歌开发者论坛上,谷歌 ...

  6. pthread中如何追踪stack over flow

    通常在程序挂掉的时候我们会catch 他们挂掉的signal,然后在signal中打印出当时的一个stack,来方便问题调查, 但是在stack overflow的情况发生时,会没有拿到stack.s ...

  7. KMP算法不同写法之间区别

    网上之所以有这么多版本的KMP算法,是因为有的人写的是最大长度串版本的,有的人写的是next数组版本的(具体区别看下面博文),有的人写的是next优化版的,有的人写的是未优化的,不同人写的循环方法不同 ...

  8. 大白话解说TCP/IP协议三次握手和四次挥手

    背景 和女朋友异地恋一年多,为了保持感情我提议每天晚上视频聊天一次. 从好上开始,到现在,一年多也算坚持下来了. 问题 有时候聊天的过程中,我的网络或者她的网络可能会不好,视频就会卡住,听不到对方的声 ...

  9. SP34096 DIVCNTK - Counting Divisors (general)(Min_25筛)

    题面 洛谷 \(\sigma_0(i)\) 表示\(i\) 的约数个数 求\(S_k(n)=\sum_{i=1}^n\sigma_0(i^k)\mod 2^{64}\) 多测,\(T\le10^4,n ...

  10. sql开发技巧总结-1

    1.数据库分类 关系型 非关系型 2.sql语句分类 sql: ddl数据库定义语言  tpl事物处理语言 dcl数据控制语言  dml数据操作语言(insert delete update sele ...