前言
本章内容为Android开发者指南的 Framework Topics/User Interface/Notifications/Status Bar Notifications章节,译为"状态栏通知",版本为Android 4.0 r1,翻译来自:"呆呆大虾",欢迎访问他的微博:"http://weibo.com/popapa",再次感谢"呆呆大虾" !期待你一起参与翻译Android的相关资料,联系我over140@gmail.com。
状态栏通知
译者署名: 呆呆大虾
版本:Android 4.0 r1
原文
http://developer.android.com/guide/topics/ui/notifiers/notifications.html
快速查看
· 状态栏(status bar)通知允许应用程序以不干扰当前activity的方式将事件通知用户。
· 可以给通知绑定一个意图(intent),当用户点击时系统会执行此意图。
在本文中
关键类
状态栏(status bar)通知将一个图标填加到系统的状态栏中(包含一条可选的提示文本信息),并将一条展开信息添加到通知窗口中。当用户选中展开信息时,Android将执行一个此通知已定义的意图Intent(通常用于弹出一个Activity)。你还可以对通知进行配置,用设备提供的声音、振动、闪光来提醒用户。
当后台服务(Service)需要对某个事件发出提醒并且需要用户响应时,状态栏通知就能发挥作用了。后台服务从来不会启动Activity来接收用户的交互,取而代之的是应该创建一个状态栏通知,在用户点选后再由通知来启动Activity。
以下截图展示了一个左侧带有通知图标的状态栏:
下图展示了“Notifications”窗口内的通知展开信息。用户可通过下拉状态栏(或在Home菜单里选中通知)来显示这个通知窗口。
Activity或者Service都能初始化一个状态栏通知。可因为Activity只有在活动状态并获得焦点时才能执行操作,所以还是建议用Service来创建状态栏通知。这样,即使用户正在使用其他程序或者设备已经休眠时,仍然可以从后台创建通知。要创建一个通知,须用到两个类:Notification类和NotificationManager类。
用Notification类的一个实例来定义状态栏通知的属性,比如图标、展开信息,以及播放声音等附属设置。NotificationManager是一个Android系统服务,用于管理和运行所有通知。NotificationManager不能被实例化,为了把Notification传给它,你可以用getSystemService()方法获取一个NotificationManager的引用。在需要通知用户时再调用notify()方法将Notification对象传给它。
要创建一个状态栏通知:
1. 获取NotificationManager的引用:
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
2. 实例化Notification:
int icon = R.drawable.notification_icon;
CharSequence tickerText = "Hello";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
3. 指定通知的展开信息和Intent:
Context context = getApplicationContext();
CharSequence contentTitle = "My notification";
CharSequence contentText = "Hello World!";
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
4. 将Notification对象传给NotificationManager:
private static final int HELLO_ID = 1;
mNotificationManager.notify(HELLO_ID, notification);
好了,现在用户已经能看到通知了。
NotificationManager管理着所有的通知,只能通过getSystemService()方法来获取它的引用。例如:
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
如果想要发送状态栏通知,通过notify(int, Notification)传递Notification对象给NotificationManager即可。第一个参数是Notification 的唯一ID,第二个参数是Notification对象。ID在整个应用程序范围内唯一标识Notification。Notification需要更新;应用程序可能管理着多种不同的通知,在用户通过各自定义的Intent返回应用程序时必须能选择正确的动作执行之,因此上述参数是必需的。
要实现用户从通知窗口内点选后自动清除状态栏通知,请在Notification对象中加入“FLAG_AUTO_CANCEL”标志。也可以传入通知ID用cancel(int)手动清除,或者用cancelAll()清除所有你创建的通知。
Notification对象定义了通知消息显示在状态栏和通知窗口上的细节内容,以及其他提醒设置(比如:声音、闪光等)。
状态栏通知必须包括以下内容:
· 状态栏图标
· 展开窗口view的标题和展开信息(除非用了自定义展开view)
· PendingIntent,当通知被点选时执行
状态栏通知的可选设置包括:
· 状态栏提示信息
· 提醒声音
· 震动设置
· LED灯闪光设置
Notification的基础库(译者注:原文是starter-kit,但综合上下文并非“初学者套件”的意思,这里译为基础库)里包含了构造方法Notification(int, CharSequence, long)和setLatestEventInfo(Context, CharSequence, CharSequence, PendingIntent)方法。这已经可以定义Notification的所有设置。以下代码段演示了对通知基本的设置:
int icon = R.drawable.notification_icon; // icon from resources
CharSequence tickerText = "Hello"; // ticker-text
long when = System.currentTimeMillis(); // notification time
Context context = getApplicationContext(); // application Context
CharSequence contentTitle = "My notification"; // expanded message title
CharSequence contentText = "Hello World!"; // expanded message text
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// the next two lines initialize the Notification, using the configurations above
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
setLatestEventInfo()方法方便地进行修改,然后再次调用notify()显示出来。
除了Context、展开信息的标题和文本外,可以利用对象的成员值修改每个属性。要修改通知的文本信息,只能对contentTitle和contentText参数赋新值并调用setLatestEventInfo(),然后再调用notify()方法来更新通知。(当然,如果已经创建了自定义扩展view,那么标题和文本的修改就无效了)。
MediaStore类的ContentProvider中获取:
notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
这时,已知有资源ID为6的媒体文件,并且已添加到Uri内容中。如果不知道确切的ID,则必须先用ContentResolver查询MediaStore中所有可用的资源。关于使用ContentResolver的详细信息请参阅Content Providers文档。
如果期望在用户响应通知或取消通知前,声音一直持续循环播放,可以把 “FLAG_INSISTENT” 加入flags属性中。
注意:如果defaults属性包含了“DEFAULT_SOUND”,则缺省提示音将覆盖sound 属性里指定的声音。
LevelListDrawable等级。通过改变这个值,可以在状态栏中显示图标的动画,这个值与LevelListDrawable中drawable的定义相关。详情请参阅LevelListDrawable。
程序能自定义更多特性,详情请参阅Notification。
setLatestEventInfo() 的contentTitle和contentText参数指定的。不过仍可以用RemoteViews来自定义一个展开视图的布局。右侧的截图就展示了一个自定义展开视图的例子,其中用到了LinearLayout 布局中的ImageView和TextView。
要自定义展开信息的布局,需要实例化一个RemoteViews对象,并将它传递给Notification的contentView属性,同时把PendingIntent传给contentIntent属性。
通过例子是对创建自定义展开视图最好的理解方式:
1. 为展开视图新建XML布局,建立一个名为custom_notification_layout.xml的布局文件,内容如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="3dp"
>
<ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#000"
/>
</LinearLayout>
此布局用于展开视图,但ImageView和TextView的内容还需要由应用程序来定义。RemoteViews提供了一些方便的方法来定义这些内容。
2. 在应用程序代码里,用RemoveViews的方法来定义图片和文字。然后把RemoteViews对象传给Notification的contentView属性,如下所示:
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
contentView.setImageViewResource(R.id.image, R.drawable.notification_image);
contentView.setTextViewText(R.id.text, "Hello, this message is in a custom expanded view");
notification.contentView = contentView;
如上:先把程序package名和布局资源ID传给RemoteViews的构造方法。然后用setImageViewResource()和setTextViewText()定义ImageView和TextView的内容,分别把View对象的资源ID、所赋的内容作为参数传入。最后,把RemoteViews对象传给Notification的contentView属性。
3. 由于自定义视图不需要执行setLatestEventInfo()方法,因此必须用contentIntent属性来定义一个通知所要执行的意图Intent ,如下:
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
4. 现在通知可以如常发送了:
mNotificationManager.notify(CUSTOM_VIEW_ID, notification);
RemoteViews类还包含了一些方法,便于在通知的展开视图里增加Chronometer或ProgressBar。关于用RemoteViews创建自定义布局的详细信息,请参阅RemoteViews 类的参考文档。
注意:当建立一个自定义展开视图时,必须特别小心,保证自定义的布局能正常工作在不同的设备方向和分辨率下。这个建议对于所有在Android上创建的View布局都是适用的,但在这种情况下尤为重要,因为布局实际可用的屏幕区域非常有限。不要把自定义布局设计得过于复杂,并且一定要在各种环境配置下进行测试。
发表评论 取消回复