翻译的好辛苦,有些地方也不太理解什么意思,如果有误,还请大神指正。
官方文档地址:http://developer.android.com/guide/topics/ui/notifiers/notifications.html
notification可以作为一条信息被显示在你的应用程序的正常UI之外。当你告诉系统去发布一条notification,它首先会在notification area(通知区域)显示一个小图标。想要去查看notification的详细内容,用户必须打开notification drawer(通知抽屉)。notification area和notification drawer都是由系统控制的区域,用户可以在任何时候查看它们。 图1.通知在通知区域(notification area) 图2.通知在通知抽屉(notification drawer) 通知设计(Notification Design) 通知,作为Android UI中重要的一部分,有它自己的设计指南。想要学习如何设计通知和它们的交互,请阅读Android设计指南(Android Design Guide) Notifications部分。 笔记:除非特别说明,本指南所引用的NotificationCompat.Builder 类是在第4版本的 Support Library. 类 Notification.Builder 在 Android 3.0被添加。 通知显示元素(Notification Display Elements) 通知在通知抽屉里能使用两种视觉样式中的一种,同时也取决于抽屉的版本与状态。(不同版本的Android的抽屉会有不同的视觉效果) 正常视图(Normal View) 通知的标准视图显示于通知抽屉中。 大视图(Big View) 当通知被扩展时,可以看见一个更大的视图。大视图只有自Android 4.1以来已拓展的通知特性的一部分。 它们的样式与描述将在下面给出。 正常视图(Normal View) 一条在正常视图中的通知显示有64dp高。虽然你创建了一个大视图的通知,但它还是会先显示正常的尺寸,直到你展开它。下面是一个正常视图的例子。 图3.在正常视图中的通知。 插图中的编号请看如下的参考: 1.内容标题(Content title) 2.大图标(Large icon) 3.内容文本(Content text) 4.内容信息(Content info) 5.小图标(Small icon) 6.通知被发布的时间,你可以通过 setWhen()来设定一个指定的值;如果你不设定的话,它将默认是系统接受到这条通知的时间。 大视图(Big View) 一个通知的大视图只有在它被展开的时候显示,这发生在通知在通知抽屉的顶部(译者注:即,通知抽屉中,第一条会自动展开。),或者当用户通过手势去展开它。展开的通知从Android 4.1开始 可用。 接下来的截屏展示了一个inbox-style的通知: 图4.大视图的通知。 通知在大视图中有着和普通视图差不多的视觉元素。这唯一的不同是标号7的地方,详细区域。每一个大视图需要设置这块区域通过不同方式。可用的样式有: 大图片样式(Big picture style) 这个详细区域包含一个256dp高的位图。 大本文样式(Big text style) 在这个区域显示一大段文本。 收件箱样式(Inbox style) 在这个区域显示一行一行的文本。 大视图的样式也有如下这些可选的,它们在正常视图中不可用: 大内容标题(Big content title) 允许你去覆写正常视图的内容标题,那个标题只在展开的视图中显示。 文本摘要(Summary text) 允许你在详细区域之上添加一行文本。 把大视图的样式应用到通知上在这里有详细的描述Applying a big view style to a notification。 创建一条通知(Creating a Notification) 你可以使用NotificationCompat.Builder对象为一条通知来指定UI的信息和行为。要创建以一个notification对象,你可以调用NotificationCompat.Builder.build(),它将返回一个Notification对象,包含着你指定的属性。要去发布这条通知,可以通过调用NotificationManager.notify()来发送它。 通知所必须的内容(Required notification contents) 一条通知对象必须包含如下内容:
NotificationCompat.Builder mBuilder = newNotificationCompat.Builder(this) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("My notification") .setContentText("Hello World!"); // 为Activity创建一个明确的Intent Intent resultIntent =newIntent(this,ResultActivity.class); // 栈建造者对象将为启动的Activity制造一个人工的回退栈 // 这样确保了在按回退键的时候,可以从启动的Activity回退到主屏幕上 TaskStackBuilder stackBuilder =TaskStackBuilder.create(this); // 为Intent添加回退栈,但不是Intent本身 stackBuilder.addParentStack(ResultActivity.class); // 添加Intent,这个Intent启动Activity并放置它到栈顶 stackBuilder.addNextIntent(resultIntent); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent( 0, PendingIntent.FLAG_UPDATE_CURRENT ); mBuilder.setContentIntent(resultPendingIntent); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // mId 允许你在之后更新这个通知 mNotificationManager.notify(mId, mBuilder.build());到这里为止,你的用户已经被通知了。 给通知应用一个大视图样式(Applying a big view style to a notification) 当通知被展开的时候,会有一个大的视图出现,首先创建一个NotificationCompat.Builder对象来添加一些你想要的可选的样式。然后调用Builder.setStyle(),把big view style对象作为参数传入。 记住,展开通知在Android 4.1之前是不可用的。想要学习如何在Android 4.1以前更早的版本上处理这个问题,参考Handling compatibility。 举个例子,接下来的代码片段示范了如何修改之前创建的通知,让它使用一个收信箱大视图样式:
NotificationCompat.Builder mBuilder =newNotificationCompat.Builder(this) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("Event tracker") .setContentText("Events received") NotificationCompat.InboxStyle inboxStyle = newNotificationCompat.InboxStyle(); String[] events =newString[6]; // 给收信箱样式的大视图设置一个标题 inboxStyle.setBigContentTitle("Event tracker details:"); ... // 将事件列表放入收信箱中 for(int i=0; i < events.length; i++){ inboxStyle.addLine(events[i]); } //将收信箱样式设置给通知对象 mBuilder.setStyle(inBoxStyle); ... // 在这里写上发布通知的代码
处理兼容性(Handling compatibility) 对于某个版本来说,并不是所有的通知的特性都是可用的,尽管在支持库中的类NotificationCompat.Builder是可以设置这些方法。比如说,行为按钮(action button),这取决于展开通知,只出现Android 4.1及更高的版本上,因为可展开的通知只在Android 4.1及更高的版本可以被使用。 为了确保最好的兼容性,使用NotificationCompat来创建通知对象,特别推荐使用NotificationCompat.Builder。另外,在实现你的通知对象的时候请遵从下面的步骤:
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 给通知设置一个ID,这个可以用来更新 int notifyID =1; mNotifyBuilder =newNotificationCompat.Builder(this) .setContentTitle("New Message") .setContentText("You've received new messages.") .setSmallIcon(R.drawable.ic_notify_status) numMessages =0; // 开启一个循环去处理数据,然后通知用户 ... mNotifyBuilder.setContentText(currentText) .setNumber(++numMessages); // 因为ID仍然存在,所以可以更新通知 mNotificationManager.notify( notifyID, mNotifyBuilder.build()); ...这段代码产生的效果看起来像这样子的: 图5.在显示的通知抽屉中更新通知 移除通知(Removing notifications) 通知会一直存在,直到下面的情况之一发生:
<activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".ResultActivity" android:parentActivityName=".MainActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"/> </activity>
2.创建一个基于启动Activity的Intent的回退栈。 a.创建Intent去启动Activity。 b.通过调用TaskStackBuilder.create()去创建栈建造者。 c.通过调用addParentStack()去添加回退栈。对于你在manifest文件中定义的每一个在层级结构中的Activity,回退栈包含一个启动Activity的Intent对象。这个方法也在一个全新的任务中添加了一个开始栈的标识符。 笔记:虽然addParentStack()的参数是关联着启动Activity。但这个方法没有添加启动Activity的Intent。取而代之的,看下一步。 d.调用addNextIntent()来添加从通知启动Activity的Intent。把在第一步中创建的Intent作为参数传给addNextIntent()。 e.如果你需要,通过调用TaskStackBuilder.editIntentAt()给Intent对象传递参数。当用户使用Back按键来导航,有时候非常有必要确保目标Activity显示有意义的数据。 f.通过调用getPendingIntent()获取一个PendingIntent。你可以把这个PendingIntent作为参数传给setContentIntent()。 下面的代码片段示范了这个过程。
... Intent resultIntent =newIntent(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 =newNotificationCompat.Builder(this); builder.setContentIntent(resultPendingIntent); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(id, builder.build());
设置一个特殊的Activity PendingIntent(Setting up a special activity pendingIntent) 接下来的几个部分描述了如何设置一个特殊的ActivityPendingIntent。 一个特殊的activity不需要回退栈,所以你可以不在manifest文件中定义activity的层级关系,你也不需要在构建回退栈的时候调用addParentStack()。取而代之的,使用manifest文件来设置activity的任务选项,通过getActivity()来创建PendingIntent。 1.在你的manifest文件中,为你的Activity添加如下属性 android-name="activityclass" activity的完整类名。 android-taskAffinity="" 与你在代码中的FLAG_ACTIVITY_NEW_TASK标识符有关,这确保了Activity不会进入应用程序的任务中。任何与应用程序默认的任务都不会受到影响。 android-excludeFromRecents="true" 排除来自“最近任务”的新任务,所以用户不会不小心导航回去。 下面代码片段显示这个xml代码
<activity android:name=".ResultActivity" ... android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true"> </activity> ...2.构建和发布通知: a.创建一个启动Activity的Intent。 b.通过调用setFlags()来设置Activity在一个全新的,空的任务中启动,可以使用如下标识符作为参数:FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TASK。 c.为Intent设置其它你需要的可选项。 d.通过调用getActivity(),从Intent中创建一个PendingIntent。你可以把这个PendingIntent当参数传给setContentIntent()。 下面的代码片段示范了这个过程。
// 实例化一个建造对象 NotificationCompat.Builder builder =newNotificationCompat.Builder(this); // 为Activity创建一个Intent Intent notifyIntent = newIntent(newComponentName(this,ResultActivity.class)); // 设置这个Activity在一个全新的,空的任务中启动 notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); // 创建PendingIntent PendingIntent notifyIntent = PendingIntent.getActivity( this, 0, notifyIntent PendingIntent.FLAG_UPDATE_CURRENT ); // 把PendingIntent放入通知 builder.setContentIntent(notifyIntent); // 通知通过通知管理器发布 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 构建一个匿名的通知发送给通知管理器 mNotificationManager.notify(id, builder.build());
在通知里显示一个进度条(Displaying Progress in a Notification) 通知可以包含一个动态的进度指示器,用来显示当前操作的进度。如果你能估计这个操作总共有多久,以及任何时间点上的完成度,那么你可以用一个“确定”格式的指示器(进度条)。如果你没法估计操作的长度,用“不确定”格式的指示器。 进度条指示器是实现了ProgressBar来执行显示的。 调用setProgress()方法来使用进度条指示器开始于Android 4.0.在之前的版本,你必须创建自己的通知布局来包含ProgressBar视图。 接下来的部分介绍了如何使用setProgress()来在通知中显示进度条。 显示一个已知长度的进度条指示器(Displaying a fixed-duration progress indicator) 为了能够显示一个确定的进度条,通过调用setProgress() setProgress(max, progress, false)给你的通知加上进度条。然后发布通知。然后,随着操作的进度,增加进度值,然后更新通知。在操作结束的时候,进度值应该等于最大值。通常的方式是调用setProgress()来设置最大值为100,然后去增加进度完成的百分比。 你可以在操作完成的时候显示进度条,也可以移除掉它。在这样的情况下,记住要去更新通知的文本,显示操作已经完成了。调用setProgress() setProgress(0, 0, false)来移除进度条。看下面这个例子:
... mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mBuilder =newNotificationCompat.Builder(this); mBuilder.setContentTitle("Picture Download") .setContentText("Download in progress") .setSmallIcon(R.drawable.ic_notification); // 在后台线程开启一个耗时操作 newThread( newRunnable(){ @Override publicvoid run(){ int incr; // 完成一个操作20次 for(incr =0; incr <=100; incr+=5){ // 给进度条设置最大值, 当前的完成度,以及“确定”状态 mBuilder.setProgress(100, incr,false); // 第一次就显示进度条 mNotifyManager.notify(0, mBuilder.build()); // 睡眠这条线程,模拟耗时操作 try{ // 睡5秒 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();效果显示在图6上。左边的截图上是通知正在执行这操作,右边的截图是通知已经完成了操作。 图6.在工作中的进度条与完成后的进度条 显示一个持续的活动指示器(Displaying a continue activity indicator) 为了能使用不确定的活动指示器,使用setProgress(0, 0, true)方法来给你的通知添加(前两个参数被忽略了),然后发布通知。除非去指定它的动画效果,要不然,这个指示器的样式都是一样的。 在操作开始的时候发布通知,这个动画将一直执行,直到你修改通知,当操作完成的时候,调用setProgress() setProgress(0, 0, false)来更新通知去移除活动指示器。我们总是这样做,除非你想要让操作完成的时候,动画效果还在运行。也请记住当操作完成的时候更新下通知里的文本。 看下面的代码来了解下活动指示器是如何工作的:
// 设置进度指示器的最大值,当前完成的百分比,以及“确定”状态 mBuilder.setProgress(100, incr,false); // 发布通知 mNotifyManager.notify(0, mBuilder.build()); 用下面的代码替换上面的代码: // 为不明确时长的操作添加一个活动指示器 mBuilder.setProgress(0,0,true); // 发布通知 mNotifyManager.notify(0, mBuilder.build());运行的结果如图7: 图7.一个持续的活动指示器。 自定义通知布局(Custom Notification Layouts) 通知的框架允许你去自定义通知的布局。通过RemoteViews对象来定义通知的外观。自定义通知布局与常规通知相似,但是它是基于定义在XML文件的RemoteViews对象来操作的。 自定义通知的可用高度是取决于通知视图的。正常的视图布局高度限制在64dp,可展开视图的布局高度限制在256dp。 为了去定义自己的通知布局,从扩充XML文件获取一个RemoteViews对象的实例开始。然后,类似于调用setContentTitle()方法一样,我们需要调用setContent()。为了能设置更多细节,我们使用RemoteViews对象的方法来设置更多的内容。 1.创建一个单独的XML文件,用来定义通知的布局。你可以使用任何你想用的名字,但后缀必须是.xml。 2.在应用里面,使用RemoteViews对象的方法来给你的通知设置文本和图标,通过调用setContent()把你的RemoteViews对象放到NotificationCompat.Builder里面。避免使用背景图像,因为你的文本可能会变得不太好阅读。 RemoteViews对象也包含一些方法用来给你去添加Chronometer和ProgressBar。想要了解更多自定义通知条布局的事情,参考RemoteViews的文档。 注意:当你使用自定义的通知条的时候,特别要注意你自定义的通知条在不同方向与分辨率的设备上是如何工作的。当然这条建议对所有的视图布局都很重要。但对通知条来说是尤其重要的,因为通知抽屉的控件十分的有限。不要把自己的通知条做的太复杂,确保它的灵活性。 为自定义的通知条文本使用样式资源(Using style resources for custom notification text) 自定义通知条的时候总是使用样式资源去定义文本。通知的背景颜色会变得与设备与当前版本的android有很大的反差。使用样式文件能帮你很好的解决这一点。从Android 2.3开始,系统就为标准的通知布局定义了文本的样式,如果你在Android2.3 以及其更高的版本上使用同样的样式,你必须确保你的文本相对于背景是可以看见的。