在Android系统中,Notification是一种具有全局效果的通知,在App开发中也很常用,今天就记录一下学习Notification的过程。
老规矩,先来一个搞笑段子:
经常熬夜有三大害处:第一,记忆力越来越差;第二,数学水平下降;第四,记忆力越来越差。
这篇文章Copy自xxbs2003的博文。因为他写的太好了,并且我不想写。
Notification
Notification,俗称通知,是一种具有全局效果的通知,它展示在屏幕的顶端,首先会表现为一个图标的形式,当用户向下滑动的时候,展示出通知具体的内容。
因为Android的快速发展,而Android的版本也快速的升级导致了一些兼容性的问题。对于Notification而言,Android3.0是一个分水岭,在其之前构建Notification推荐使用NotificationCompate.Builder,它位于android.support.v4.app.NotificationCompat.Builder,是一个Android向下版本的兼容包,而在Android3.0之后,一般推荐使用Notification.Builder构建。本博客主要介绍的是Android4.x的开发,所以在这里使用Notification.Builder进行讲解演示。
通知一般通过NotificationManager服务发送一个Notification对象来完成通知,NotificationManager是一个重要的系统级服务,该对象位于应用程序的框架层中,应用程序可以通过它向系统发送全局的通知。使用通知的时候,需要创建一个Notification对象用来承载通知的内容,但是一般不会直接通过Notification的构造方法来得到对象,而是使用它的内部类Notification.Builder来实例化一个Builder对象,并设置通知的各项属性,最后通过Notification.Builder.builder()方法得到一个Notification对象,当获得这个Notification对象之后,就可以使用NotificationManager.notify()方法发送通知。
NotificationManager类是一个通知管理器类,这个对象是由系统维护的服务,是以单例模式的方式获得,所以一般并不直接实例化这个对象。在Activity中,可以使用Activity.getSystemService(String)方法获取NotificationManager对象,Activity.getSystemService(String)方法可以通过Android系统级服务的句柄,返回对应的对象。在这里需要返回NotificationManager,所以直接传递Context.NOTIFICATION_SERVICE即可。
虽然通知中提供了各种属性的设置,但是一个通知对象,有几个属性是必须要设置的,其他的属性均是可选的,必须设置的属性如下:
- 小图标,使用setSamllIcon()方法设置。
- 标题,使用setContentTitle()方法设置。
- 文本内容,使用setContentText()方法设置。
更新与移除通知
在使用NotificationManager.notify()发送通知的时候,需要传递一个标识符,用于唯一标识这个通知。对于有些场景,并不是无限的添加新的通知,有时候需要更新原有通知的信息,这个时候可以重写构建Notification,而使用与之前通知相同标识符来发送通知,这个时候旧的通知就被被新的通知所取代,起到更新通知的效果。
对于一个通知,当展示在状态栏之后,但是使用过后,如何取消呢?Android为我们提供两种方式移除通知,一种是Notification自己维护,使用setAutoCancel()方法设置是否维护,传递一个boolean类型的数据。另外一种方式使用NotificationManager通知管理器对象来维护,它通过notify()发送通知的时候,指定的通知标识Id来操作通知,可以使用cancel(int)来移除一个指定的通知,也可以使用cancelAll()移除所有的通知。
使用NotificationManager移除指定通知示例:
1 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
2 mNotificationManager.cancel(0);
PendingIntent
对于一个通知而言,它显示的消息是有限的,一般仅用于提示一些概要信息。但是一般简短的消息,并不能表达需要告诉用户的全部内容,所以需要绑定一个意图,当用户点击通知的时候,调用一个意图展示出一个Activity用来显示详细的内容。而Notification中,并不使用常规的Intent去传递一个意图,而是使用PendingIntent。
先来说说Intent和PendingIntent的区别,PendingIntent可以看做是对Intent的包装,通过名称可以看出PendingIntent用于处理即将发生的意图,而Intent用来用来处理马上发生的意图。而对于通知来说,它是一系统级的全局通知,并不确定这个意图被执行的时间。当在应用外部执行PendingIntent时,因为它保存了触发应用的Context,使得外部应用可以如在当前应用中一样,执行PendingIntent里的Intent,就算执行的时候响应通知的应用已经被销毁了,也可以通过存在PendingIntent里的Context照常执行它,并且还可以处理Intent说带来的额外信息。
PendingIntent提供了多个静态的getXxx()方法,用于获得适用于不同场景的PendingIntent对象。一般需要传递的几个参数都很常规,只介绍一个flag参数,用于标识PendingIntent的构造选择:
- FLAG_CANCEL_CURRENT:如果构建的PendingIntent已经存在,则取消前一个,重新构建一个。
- FLAG_NO_CREATE:如果前一个PendingIntent已经不存在了,将不再构建它。
- FLAG_ONE_SHOT:表明这里构建的PendingIntent只能使用一次。
- FLAG_UPDATE_CURRENT:如果构建的PendingIntent已经存在,则替换它,常用。
Notification视觉风格
Notification有两种视觉风格,一种是标准视图(Normal view)、一种是大视图(Big view)。标准视图在Android中各版本是通用的,但是对于大视图而言,仅支持Android4.1+的版本。
从官方文档了解到,一个标准视图显示的大小要保持在64dp高,宽度为屏幕标准。标准视图的通知主体内容有一下几个:
- 通知标题。
- 大图标。
- 通知内容。
- 通知消息。
- 小图标。
- 通知的时间,一般为系统时间,也可以使用setWhen()设置。
下面通过一个示例,模仿上面效果的通知。
1 btnNotification.setOnClickListener(new View.OnClickListener() {
2
3 @Override
4 public void onClick(View v) {
5 Bitmap btm = BitmapFactory.decodeResource(getResources(),
6 R.drawable.msg);
7 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
8 MainActivity.this).setSmallIcon(R.drawable.msg)
9 .setContentTitle("5 new message")
10 .setContentText("[email protected]");
11 mBuilder.setTicker("New message");//第一次提示消息的时候显示在通知栏上
12 mBuilder.setNumber(12);
13 mBuilder.setLargeIcon(btm);
14 mBuilder.setAutoCancel(true);//自己维护通知的消失
15
16 //构建一个Intent
17 Intent resultIntent = new Intent(MainActivity.this,
18 ResultActivity.class);
19 //封装一个Intent
20 PendingIntent resultPendingIntent = PendingIntent.getActivity(
21 MainActivity.this, 0, resultIntent,
22 PendingIntent.FLAG_UPDATE_CURRENT);
23 // 设置通知主题的意图
24 mBuilder.setContentIntent(resultPendingIntent);
25 //获取通知管理器对象
26 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
27 mNotificationManager.notify(0, mBuilder.build());
28 }
29 });
显示效果:
而对于大视图(Big View)而言,它的细节区域只能显示256dp高度的内容,并且只对Android4.1+之后的设备才支持,它比标准视图不一样的地方,均需要使用setStyle()方法设定,它大致的效果如下:
setStyle()传递一个NotificationCompat.Style对象,它是一个抽象类,Android为我们提供了三个实现类,用于显示不同的场景。分别是:
- NotificationCompat.BigPictureStyle, 在细节部分显示一个256dp高度的位图。
- NotificationCompat.BigTextStyle,在细节部分显示一个大的文本块。
- NotificationCompat.InboxStyle,在细节部分显示一段行文本。
如果仅仅显示一个图片,使用BigPictureStyle是最方便的;如果需要显示一个富文本信息,则可以使用BigTextStyle;如果仅仅用于显示一个文本的信息,那么使用InboxStyle即可。后面会以一个示例来展示InboxStyle的使用,模仿上面图片的显示。
实现代码:
1 btnBigViewNotification.setOnClickListener(new View.OnClickListener() {
2
3 @Override
4 public void onClick(View v) {
5
6 Bitmap btm = BitmapFactory.decodeResource(getResources(),
7 R.drawable.msg);
8 Intent intent = new Intent(MainActivity.this,
9 ResultActivity.class);
10
11 PendingIntent pendingIntent = PendingIntent.getActivity(
12 MainActivity.this, 0, intent,
13 PendingIntent.FLAG_CANCEL_CURRENT);
14
15 Notification noti = new NotificationCompat.Builder(
16 MainActivity.this)
17 .setSmallIcon(R.drawable.msg)
18 .setLargeIcon(btm)
19 .setNumber(13)
20 .setContentIntent(pendingIntent)
21 .setStyle(
22 new NotificationCompat.InboxStyle()
23 .addLine(
24 "M.Twain (Google+) Haiku is more than a cert...")
25 .addLine("M.Twain Reminder")
26 .addLine("M.Twain Lunch?")
27 .addLine("M.Twain Revised Specs")
28 .addLine("M.Twain ")
29 .addLine(
30 "Google Play Celebrate 25 billion apps with Goo..")
31 .addLine(
32 "Stack Exchange StackOverflow weekly Newsl...")
33 .setBigContentTitle("6 new message")
34 .setSummaryText("[email protected]"))
35 .build();
36
37 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
38 mNotificationManager.notify(0, noti);
39 }
40 });
展示效果: