您的位置:首页 > 移动开发 > Android开发

[Android]状态栏通知Notification、NotificationManager详解

2014-03-26 18:29 537 查看

原文链接

参考的原文链接:http://www.cnblogs.com/plokmju/p/android_Notification.html

前言

这篇文章主要是记录一下项目中Notification的使用,我用它来做了一个下载进度的显示。之所以这里记录,是因为实现notification可以使用Notification、Notification.Builder、NotificationCompat.Builder三个类,开始快被这三个类搞糊涂了,因此这里记录一下学习过程。

Android官网解释

我发现学习Android最好的网站是stackoverflow,其次就是安卓官网,讲的内容感觉比一些中文博客清楚很多,猜测原因应该就是Android的更新速度太快,大家忙到没时间写博客吧,哈哈,扯多了,回来继续看一下官网对这三个类的解释:

Notification:

A class that represents how a persistent notification is to be presented to the user using the NotificationManager.

The Notification.Builder has been added to make it easier to construct Notifications.

Notification.Builder:

Builder class for Notification objects. Provides a convenient way to set the various fields of a Notification and generate content views using the platform's notification layout template. If your app supports versions
of Android as old as API level 4, you can instead use NotificationCompat.Builder, available in the Android Support library.

NotificationCompat.Builder:

Builder class for NotificationCompat objects. Allows easier control over all the flags, as well as help constructing the typical notification layouts.

On platform versions that don't offer expanded notifications, methods that depend on expanded notifications have no effect.

For example, action buttons won't appear on platforms prior to Android 4.1. Action buttons depend on expanded notifications, which are only available in Android 4.1 and later.

For this reason, you should always ensure that UI controls in a notification are also available in an Activity in your app, and you should always start that Activity when users click the notification. To do this, use the setContentIntent() method.

上述内容其实已经很容易理解了,我更直白的说一下:Notification里面很多方法都被废弃了,使用的话在Eclipse里会有很恶心的划线和warning警告(我受不了这个),Android现在推荐使用Notification.Builder来创建notication,但是如果要兼容Android1.6等比较老的版本,推荐使用NotificationCompat.Builder来构建notification。因此我这里选择使用NotificationCompat.Builder。

概述

在Android系统中,发一个状态栏通知还是很方便的。发送一个状态栏通知必须用到两个类:NotificationManager、NotificationCompat.Builder

NotificaionManager : 是状态栏通知的管理类,负责发送通知、清除通知等。它是一个系统Service,必须通过getSystemService()方法来获取。代码示例如下:

NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);


NotificationCompat.Builder:具体的状态栏通知对象的创建者,这里提一下必须要设置的属性(特别是SmallIcon),不设置的话会导致Notification不显示,必须要设置的属性如下:

小图标,通过setSmallIcon()方法设置
通知栏标题,通过setContentTitle()方法设置
通知栏内容,通过setContentText()方法设置

可选设置中有个重要的contentIntent,这里需要介绍一下。

PendingInteng

对于一个通知而言,它能显示的消息内容是有限的,但是内容有限的信息,往往不能表达需要告诉用户的全部内容,因此需要绑定一个Intent。当用户点击通知的时候,调用一个Intent展示出一个Activity用来显示详细的内容。在NotificationCompat.Builder中,并不使用常规Intent去传递一个意图,而是使用PendingIntent。

Intent和PendIntent的区别:

PendingIntent可以看做是对Intent的包装,通过名称可以看出PendingIntent用于处理即将发生的意图,而Intent用来处理马上发生的意图。而对于通知来说,它是一系统级的全局通知,并不确定这个意图被执行的时间。当在应用外部执行PendingIntent时,因此它保存了触发应该的Context,使得外部应用可以如在当前应用中一样,执行PendingInteng里的Intent,就算执行的时候响应通知的应用已经被销毁了,也可以通过存在PendingIntent里的Context照常执行它,并且还可以处理Intent带来的额外信息。

Notification视觉风格

Notification有两种视觉风格,一种是标准视图(Normal view),一种是大视图(Big view)。标准视图在Android中各版本是通用的,但是对于大视图而言,仅支持Android4.1+的版本

从官方文档了解到,一个标准视图显示的大小要保持在64dp高,宽度为屏幕标准。标准视图的通知主体内容有以下几个:



说明一下对应关系:

通知标题。
大图标。
通知内容。
通知消息。
小图标。
通知的时间,一般为系统时间,也可以使用setWhen()设置。

下面使用一个示例,模仿上面效果的通知:

Bitmap btm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent startIntent = new Intent(this, SecondActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, startIntent, 0);

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle("5 new messages")
.setLargeIcon(btm)
.setContentText("wzyll1314@gmail.com")
.setNumber(12)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent);

Notification notification = notificationBuilder.build();

notificationManager.notify(0, notification);


显示效果:



进度条样式通知

对于一个标准通知,有时候显示的消息并不一定是静态的,还可以设定一个进度条用于显示事务完成的进度。

Notification.Builder类中提供了一个setProgress(int max, int progress, boolean indeterminate)方法用于设置进度条,max用于设定进度的最大数,progress用于设定当前的进度,indeterminate用于设定是否是一个确定进度的进度条。通过indeterminate的设置,可以实现两种不同样式的进度条,一种是有进度刻度的(true),一种是循环流动的(false)。下面分别用示例来演示:

Bitmap btm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

Intent startIntent = new Intent(this, SecondActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, startIntent, 0);

notificationBuilder = new NotificationCompat.Builder(
this).setContentTitle("5 new messages").setLargeIcon(btm)
.setContentText("wzyll1314@gmail.com").setNumber(12)
.setSmallIcon(R.drawable.ic_launcher).setContentIntent(pIntent);

// 通过一个子线程,动态增加进度条刻度
new Thread(new Runnable() {

@Override
public void run() {
int incr;

for (incr = 0; incr <= 100; incr += 5) {
notificationBuilder.setProgress(100, incr, false);
notificationManager.notify(NOTIFY_ID, notificationBuilder.build());

try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

notificationBuilder.setContentText("下载完成").setProgress(0, 0, false);
notificationManager.notify(NOTIFY_ID, notificationBuilder.build());
}
}).start();


显示效果:



流动的进度条将indeterminate设置为true即可

自定义通知

和Toast一样,通知也是可以使用自定义的XML来定义样式的,但是对于通知而言,因为它的全局性,并不能简单的通过inflate一个View,因为可能触发通知的时候,响应的App已经关闭,无法获取当时指定的XML布局文件。所以需要使用单独的一个RemoteViews类来操作。

RemoteViews,描述了一个视图层次的结构,可以显示在另一个进程。层次结构也是从布局文件中inflate出一个视图,这个类,提供了一些基本的操作来修改infalte的内容。

RemoteViews提供了多个构造函数,一般使用RemoteViews(String packageName,int layoutId)。第一个参数为包的名称,第二个为layout资源的Id。当获取到RemoteViews对象之后,可以使用它的一系列setXxx()方法通过控件的Id设置控件的属性。最后使用NotificationCompat.Builder.setContent(RemoteViews)方法设置它到一个Notification中。

自定义的XML代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp" >

<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_marginRight="10dp"
android:contentDescription="@string/content_description" />

<TextView
android:id="@+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/image_view" />

<TextView
android:id="@+id/next_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title_text"
android:layout_toRightOf="@id/image_view" />

</RelativeLayout>


实现代码:

RemoteViews contentViews = new RemoteViews(getPackageName(), R.layout.custom_notification);
// 通过控件id设置属性
contentViews.setImageViewResource(R.id.image_view, R.drawable.ic_launcher);
contentViews.setTextViewText(R.id.title_text, "自定义通知标题");
contentViews.setTextViewText(R.id.next_text, "自定义通知内容");

Intent intent = new Intent(this, SecondActivity.class);

PendingIntent pIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("我的标题")
.setContent(contentViews)
.setContentIntent(pIntent)
.setAutoCancel(true);

NotificationManager nManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

nManager.notify(0, nBuilder.build());;


效果展示:



自定义的太丑了,还是用系统自带的吧,按照标准的来比较好

设定提示响应

对于某些通知,需要调用一些设备的资源,使用户能更快的发现有新通知,一般可设定的响应有:铃声、闪光灯、震动。对于这三个属性,NotificationCompat.Builder提供了三个方法设定:

setSound(Uri sound):设定一个铃声,用于在通知的时候响应。传递一个Uri的参数,格式为“file:///mnt/sdcard/Xxx.mp3”。
setLights(int argb, int onMs, int offMs):设定前置LED灯的闪烁速率,持续毫秒数,停顿毫秒数。
setVibrate(long[] pattern):设定震动的模式,以一个long数组保存毫秒级间隔的震动。
大多数时候,我们并不需要设定一个特定的响应效果,只需要遵照用户设备上系统通知的效果即可,那么可以使用setDeafults(int)方法设定默认响应参数,在Notification中,对它的参数使用常量定义了,我们只需要使用即可:

DEFAULT_ALL:铃声、闪光、震动均系统默认。
DEFAULT_SOUND:系统默认铃声。
DEFAULT_VIBRATE:系统默认震动。
DEFAULT_LIGHTS:系统默认闪光。

而在Android中,如果需要访问硬件设备的话,是需要对其进行授权的,所以需要在清单文件AndroidManifest.xml中增加两个授权,分别授予访问振动器和闪光灯的权限:

<!-- 闪光灯权限 -->
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<!-- 振动器权限 -->
<uses-permission android:name="android.permission.VIBRATE"/>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: