赞
踩
通知是可以在应用常规UI外部向用户显示的消息。通常使用NotificationCompat.Builder对象构建UI信息和操作,NotificationCompat.Builder.build()返回具体的Notification对象,最后通过调用NotificationManager.notify()将Notification对象传递给系统。
Notification必须包含以下内容:小图标(smallIcon),标题(ContentTitle),详细文本(ContentText)。
通知操作:当用户点击时触发的操作。一般会在应用打开Activity。在Notification内部,操作由PendingIntent定义,后者包含在应用中启动activity的Intent,通过setContentIntent()来添加PendingIntent。
通知优先级:优先级用于提醒设备UI如何显示通知。通过NotificationCompat.Builder,setPriority()并传入一个NotificationCompat优先级常量。共五个,从PRIORITY_MIN(-2)到PRIORITY_MAX(2);默认为PRIORITY_DEFAULT(0);
创建简单通知:
- NotificationCompat.Builder mBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.notification_icon)
- .setContentTitle("My notification")
- .setContentText("Hello World!");
- ...
- NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- // mId用于之后更新notification
- mNotificationManager.notify(mId, mBuilder.build());
扩展布局:在4.1之前不可用。
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.notification_icon)
- .setContentTitle("多文本可扩展标题")
- .setContentText("多文本可扩展内容")
- // 多文本,可扩展
- .setStyle(new NotificationCompat.BigTextStyle()
- .bigText(msg))
- .addAction (R.drawable.ic_stat_dismiss,
- getString(R.string.dismiss), piDismiss)
- .addAction (R.drawable.ic_stat_snooze,
- getString(R.string.snooze), piSnooze);
-
- ...
兼容性处理:如,扩展通知仅在Android4.1及更高版本可用等。
为了确保兼容性,需要使用NorificationCompat及其子类创建通知。此外请遵循以下流程:
1.为用户提供通知的全部功能,无论何种版本的Android系统。因此要验证是否可以从应用的Activity中获得所有功能。要实现这个要求,可能要添加新的Activity;例如,若要使用addAction()提供停止和启动媒体播放的控件,应先在Activity中实现此控件。
2.确保用户均可通过点击通知启动Activity来获得该Activity中的功能。为此,要创建PendingIntent。调用setContentIntent()以将PendingIntent添加到通知。
3.将要使用的扩展通知功能添加到通知。添加的任何功能必须在用户点击通知时启动的activity中可用。
同一类型的事件多次发生时,要避免重新发送多次的通知。使用notify()所用的通知ID来更新或创建通知。
- mNotificationManager =
- (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- // 设置通知id,以便更新
- int notifyID = 1;
- mNotifyBuilder = new NotificationCompat.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());
- ...

用户单独或通过使用“全部清除”清除了该通知(如果通知可以清除);
用户点击通知,并且创建通知时调用了setAutoCancel();
针对特定的通知ID调用了cancel()。此方法还会删除当前通知;
调用了cancelAll()方法,该方法删除之前所发出的所有通知。
从通知启动Activity时,必须保留用户的预期导航体验。点击“返回”应使用户将应用的正常工作流返回到主屏幕,点击“最新动态”则应将Activity显示为单独的任务。要保留导航体验,应该在全新任务中启动Activity。如何设置PendingIntent以获得全新任务取决于启动的Activity的性质。一般有两种情况:
要启动的Activity是应用的正常工作流的一部分。这种情况下,设置PendingIntent以启动全新任务并为PendingIntent提供返回栈,这将重现应用的正常“返回”行为。例如正在别的应用时,点击了邮件的通知,点击返回,则会依次转到收件箱和主屏幕,而不是之前的那个应用。
1)在清单文件中定义应用的Activity层次结构;
a.添加对Android4.0.3及更低版本的支持。通过添加<meta-data>元素作为<activity>的子项来指定正在启动的Activity的父项(父Activity)。
b.添加对Android4.1及更高版本的支持,将android:parentActivityName属性添加到正在启动的Activity的<activity>元素中。
示例如下:
- <activity
- android:name=".MainActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android: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()将返回栈添加到堆栈生成器。对于在清单文件中所定义层次结构内的每个Activity,返回栈均可包含可启动Activity的Intent对象。此方法还会添加一些可在全新任务中启动堆栈的标志。(注:尽管addParentStack()的参数是对已启动Activity的引用,但是方法调用不会添加可启动Activity的Intent,而是留待下一步进行处理)
d.如果调用addNextIntent(),添加可从通知中启动Activity的Intent。将在第一步中创建的Intent作为addNextIntent的参数传递。
e.如需,通过调用TaskStackBuilder.editIntentAt()向堆栈中的Intent对象添加参数。有时,需要确保目标Activity在用户使用“返回”导航回它时会显示有意义的数据。
f.调用getPendingIntent()获得此返回栈的PendingIntent。使用此PendingItent作为setContentIntent()的参数。
- ...
- 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());

注意:此处的示例在模拟器上可能展现不出效果。
仅当从通知启动时,用户才会看到此Activity。可以视Activity为通知的扩展。这种情况将PendingIntent设置为在全新的任务中启动。但由于启动的Activity不是应用Activity流程的一部分,因此无需创建返回栈。点击返回会将用户带到主屏幕。
不必在清单文件中定义Activity层次结构,也不必调用addParentStack()来构建返回栈。可以使用清单文件设置Activity任务选项,并通过调用getActivity()创建PendingIntent:
1)在清单中添加以下属性:
android:name="activityclass",全限定类名;
android:taskAffinity="",与在代码中设置的FLAG_ACTIVITY_NEW_TASK标志相结合,确保Activity不会进入应用的默认任务。任何具有应用默认关联的现有任务均不受影响。
android:excludeFromRecents="true",将新任务从“最新动态”中排除,这样用户就不会再无意中导航回它。
示例:
- <activity
- android:name=".ResultActivity"
- ...
- android:launchMode="singleTask"
- android:taskAffinity=""
- android:excludeFromRecents="true">
- </activity>
2)构建并发出通知
a.创建可启动Activity的Intent;
b.通过使用FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TASK标志调用setFlags(),将Activity设置为在新的空任务中启动;
c.为Intent设置所需的任何其他选项;
d.调用getActivity()从Intent中创建PendingIntent。使用该PendingIntent作为setContentIntent的参数。
示例:
- NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
- // 为activity创建intent
- Intent notifyIntent = new Intent(this, ResultActivity.class);
- // 设置activity启动一个新的空栈
- notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- // 创建PendingIntent
- PendingIntent notifyPendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- // 把PendingIntent放到builder中
- builder.setContentIntent(notifyPendingIntent);
- // Notifications 发送给 NotificationManager
- NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- // 通过builder构建一个匿名Notification对象并传递给NotificationManager
- mNotificationManager.notify(id, builder.build());
通知中可以显示进度条。如果可以估计操作时间以及完成进度,使用可指定进度的进度条。否则,使用无限循环进度条。
要在Android4.0及更高版本的平台上使用进度条,要调用setProgress()。早期版本,需要创建包含ProgressBar视图的自定义通知布局。
通过setProgress(max, progress, false)将进度栏添加到通知,然后发出通知。操作结束,progress等于max。常见方式是,max为100,progress作为百分比值递增。
操作完成后可以保留进度栏,也可删除。但是都要更新通知文本以显示操作已完成。要删除进度栏,调用setProgress(0, 0, false)。
- ...
- mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- mBuilder = new NotificationCompat.Builder(this);
- mBuilder.setContentTitle("Picture Download")
- .setContentText("Download in progress")
- .setSmallIcon(R.drawable.ic_notification);
- // 在后台线程进行冗长操作
- new Thread(
- new Runnable() {
- @Override
- public void run() {
- int incr;
- // 20次冗长操作
- for (incr = 0; incr <= 100; incr+=5) {
- // 设置进度指示器最大值,完成值,确定状态
- mBuilder.setProgress(100, incr, false);
- // 第一次时,显示进度栏
- mNotifyManager.notify(0, mBuilder.build());
- try {
- Thread.sleep(5*1000);
- } catch (InterruptedException e) {
- Log.d(TAG, "sleep failure");
- }
- }
- // 当循环完成,更新notification
- mBuilder.setContentText("Download complete")
- // 移除进度栏
- .setProgress(0,0,false);
- mNotifyManager.notify(ID, mBuilder.build());
- }
- }
- // 启动线程
- ).start();

使用setProgress(0, 0, true)添加到通知(忽略前两个参数),然后发出通知。setProgress(0, 0, false)可以删除指示器,不删除的话会一直显示。
使用RemoteViews对象自定义通知布局。自定义布局的可用高度取决于通知视图。普通视图布局限制为64dp,扩展视图布局限制为256dp。
首先实例化RemoteViews来扩充XML布局文件,调用setContent()方法设置详细内容,注意要使用RemoteViews中的方法设置视图子项的值:
1.在单独文件中为通知创建XML布局。
2.避免为RemoteViews设置背景Drawable,背景色可能使文本难以阅读。
这里按照文档描述的很简洁,以后出一个RemoteViews的详细版本。
1)当设备处于“优先”模式时,setCategory()会告知系统如何处理应用通知(如,通知代表电话呼入、消息、闹铃);
2)如果优先级设为PRIORITY_MAX或PRIORITY_HIGH,通知会有声音或振动,则setPriority()会将其显示在小型浮动窗口中;
3)addPerson()允许向通知添加人员名单。
5.0之后,设备处于活动状态时,即屏幕已打开,可以显示为浮动通知(在屏幕顶部出现notification,不需要拉开就能看见)。也可以提供一些操作按钮。
触发条件包括:用户的Activity处于全屏模式中(应使用fullScreenIntent),或者通知具有较高的优先级并使用铃声或振动。
fullScreenIntent要使用bulder.setFullScreenIntent(pendingIntent, true);// 官网上说有些系统会选择直接启动该Activity,有些则会显示为浮动通知。测三个真机都直接启动。
5.0之后,通知可以显示在锁定屏幕上。可以用此功能提示媒体播放控件。用户在“设置”中可选择通知是否显示在锁定屏幕上。
1)调用setVisibility()指定是否可见:
a.VISIBILITY_PUBLIC:显示通知的完整内容;
b.VISIBILITY_SECRET:不在锁定屏幕上显示;
c.VISIBILITY_PRIVATE:显示通知图标和内容等基本信息,隐藏内容。
这里是指在锁屏状态可以看见通知,但是不好说,国内定制机太多,像华为荣耀就不显示,魅族会显示,但是上面几个可见性不起作用,魅族全部显示。
2)锁屏状态控制媒体播放
Android5.0(API21),锁屏不再基于RemoteControlClient显示媒体控件。而是用Notification.MediaStyle与addAction()方法结合。后者将操作转换为可点击的图标。
注意:该模板和addAction()方法未包含在支持库中,因此只有5.0及以上版本才能支持。且要将可见性设置为VISIBILITY_PUBLIC。
下面给出代码,测试的时候魅族可以显示,华为荣耀7可以在下拉的通知栏里显示,但是不显示在锁屏屏幕上。
- Notification notification = new Notification.Builder(context)
- // 设置可见性
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setSmallIcon(R.drawable.ic_stat_player)
- // 添加媒体控制按钮调用媒体service中的intent。
- .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
- .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1
- .addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2
- // 应用媒体style模板
- .setStyle(new Notification.MediaStyle()
- .setShowActionsInCompactView(1 /* #1: pause button */)
- .setMediaSession(mMediaSession.getSessionToken())
- .setContentTitle("Wonderful music")
- .setContentText("My Awesome Band")
- .setLargeIcon(albumArtBitmap)
- .build();

赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。