notification,通知,显示在状态栏那里的信息。它看起来是这样的:
如果想设计更为人性化的notification,可参考android官方的design文档————notification
- 创建notification
类似于AlertDialog的创建,notification的创建同样也是通过NotificationCompat.Builder来设置ui界面然后调用Builder.build()方法创建。当你想展示你的notification时,通过调用NotificationManager.notify()来把你的notification对象传给系统。
- notification必须要有的内容
a.小图标。通过setSmallIcon()设置
b.标题。通过setContentTitle()设置
c.内容。通过setContentText()设置
- 其他可选的内容
都定义在了NotificationCompat.Builder中,可查看Builder类查看相关内容。
- notification的action
虽然理论上来说可以不定义action,但一般一个notification至少要有一个Action(一般来说是打开对应的activity),来跳转到对应页面进行相应的操作。嘿嘿,我们也可以添加button到notification中添加一些额外的操作(android4.1引进),当用户点击时实现相应操作。如果添加了action button,那么也应该在activity中也实现button对应的功能。(为了兼容)
怎么定义action?就是给notification对应的部分设置PendingIntent,PendingIntent可打开activity等组件。要设置action,则需调用相应的方法设置PendingIntent。
如实现用户点击contenttext时跳转activity则调用setContentIntent()方法。
- Notification 优先权
作用:设置不同的重要程度,对应不同的提醒的方式。如设置为最重要的时候会弹出页面等。通过Builder.setPrioriy方法设置。
如何合适设置priority,请查看guide文档。
- 创建一个简单的notification
private void sendNotifiction() {
NotificationCompat.Builder builder = new Builder(getActivity());
builder.setContentTitle("NotifictionDemo").setContentText("i am 多啦a梦?").setSmallIcon(R.drawable.littlicon);
Intent intent = new Intent(getActivity(),ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getActivity());
stackBuilder.addParentStack(ResultActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(mId, builder.build());
}
上面的TaskStackBuilder是为了让用户跳转到对应的activity后,如果点击backButton 可以让你回到主屏幕。下面的一个部分会详细说说。
上面方法调用后,效果是这样的:
- 给notification一个拓展的布局
。。。有什么用?为毛我弄了没效果?
- 兼容性处理
并不是所有的android版本都能实现你所定义的notification的功能(如4.1前不能添加action button),为此,我们需要在activity中提供对应的acitonbutton的功能,已满足低版本的需求。
为追求最好的兼容性,推荐使用NotificationCompat.Builder类构建notification。此外,推荐依据以下的模式实现notification:
1.把所有的功能在所启动的activity内先实现。(如音乐暂停,下一首等)。
2.确保所有的user都能通过点击notification进入对应的activity中。所以创建PendingIntent与对应部分绑定。
3.添加一些功能在notification中。如点击某button暂停播放音乐
- Notification管理
有时候,你会发布多个同类型的notification,但要避免每一个创建一个notification。你可能会想要更新它,或添加一个新的。(如qq邮箱,当有多封接收的邮件时,它会更新,把所有的未读邮件放到一个inbox里,这样就只是用了一个notification。)
注意,inbox引进自android4.1
- Notification更新
how?你在前面NotificationManager.notify()时有一个id,系统通过辨认Notification的id和对应id的Notification是否已移除来决定是更新一个Notification还是添加一个Notification。
例:
final int notifictionId = 321;
int currentNoti = 0;
private void sendUpdateNotifiction() {
NotificationCompat.Builder builder = new Builder(getActivity());
builder.setContentTitle("NotifictionDemo").setContentText("多啦a梦"+currentNoti++).setSmallIcon(R.drawable.littlicon);
Intent intent = new Intent(getActivity(),ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getActivity());
stackBuilder.addParentStack(ResultActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(notifictionId, builder.build());
}
方法调用效果:
如果不是采用更新的方式(即不同的id),则如图:
2.Notifications移除
以下4中事件发生的时候,notification会消失:
1.在notification下拉中,用户点击《清除所有》button;
2.用户点击了你的notification,同时在创建notification使设置了setAutoCancel 方法为true。如果你并为调用Builder.setAutoCancel方法为true,则用户点击了该notification后,该notification依然存在。
3.调用了NotificationManager.cancel()方法,参数id为指定的notification的id。
4.调用了NotificationManager.cancelAll()方法。
- 实现通过notification所打开的Activity的导航
当你通过一个notification打开对应activity时,应该提供一个activity的导航功能:当在该activity点击back button时返回桌面;查看最近打开的应用程序列表时能看到该activity。为此,你需要在一个新的栈中启动这个activity。如何使用PendingIntent去提供一个新的Activity栈基于你如何启动这个Activity。通常来说有两种情况:
1.普通的Activity
就是通过普通方式打开应用程序同样也可以看到的Activity。对于这种情况,我们利用PendingIntent建立一个新的栈,并实现一种如同从普通方式打开应用程序时的导航模式。并且它不在乎你是否正在使用该程序,通过Notification打开的Activity都不会变。
如:我已打开:邮箱》写邮件。此时收到了新的邮件,并点击该Notification进入阅读该邮件,那么我一直按back的导航的顺序是这样的:邮件详细》邮件列表》邮件主页》home。
2.特殊的Activity
即只能通过Notification查看的Activity。通过普通方式进入应用程序里面看不到该Activity。在这种情况下,让PendingIntent开启一个新的栈,因为这个Activity与应用程序里的Activity并没什么关系,所以让它点击后直接返回home。
1.设置普通的Activity的PendingIntent
步骤:
1.在Manifest文件中定义应用程序的Activity间层级关系:
a.为支持4.1版本前,需要通过定义name为android.support.PARRENT_ACTIVITY的meta-data。
b.为支持4.1及后版本,activity标签中定义元素android:parentActivityName的值。
For Example
<activity
android:name="com.example.notificationdemo.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="com.example.notificationdemo.ResultActivity"
android:parentActivityName="com.example.notificationdemo.MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.notificationdemo.MainActivity" />
</activity>
2. 基于启动 Activity 的 Intent 来创建一个回退栈。
a . 创建启动 Activity 的 Inent
b . 通过调用 TaskStackBuilder.creat() 来创建一个 Stack Builder 实例
c . 通过调用 addParentStack () 把回退栈添加到 StackBuilder 实例中 , 根据你在 Manifest 文件中定义的 Activity 的父子关系,该操作会把所有启动父 Activity 的 Intent 都放入到栈中。但还没添加启动该 Activity 的 Inent
d . 通过调用 addNextInent 方法把启动该 Activity 的 Intent 放入栈中。
e . 当你需要给 Intent 添加参数时,你可直接添加 extra 到 Intent 中,或通过 TaskStackBuilder.editIntentAt ( ) 方法获得指定位置的 Intent 然后放入 extra 。这在有些时候是比较有用的。
f.通过调用Builder.getPendingIntent()方法获取PendingIntent。然后使用该PendingIntent。
Example:
NotificationCompat.Builder builder = new Builder(getActivity()); builder.setContentTitle("NotifictionDemo").setContentText("i am 多啦a梦?").setSmallIcon(R.drawable.littlicon); Intent intent = new Intent(getActivity(),ResultActivity.class); TaskStackBuilder stackBuilder = TaskStackBuilder.create(getActivity()); stackBuilder.addParentStack(getActivity()); stackBuilder.addNextIntent(intent); PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent); NotificationManager mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(mId, builder.build());
2. 特殊的 Activity
由于它并没和其他 Activity 有联系,所以,在一个全新的,没有其他 Activity 的栈中打开它。同时,也不需要再最近任务看到该 Activity 。
步骤:
1. 在 Manifest 文件中定义 activity 及其属性。
android:taskAffinity=""作用:设置该 Activity 没有与之有联系的 activity 。与 Intent 的 FLAG_ACTIVITY_NEW_STACK 一起使用,确保 activity 在一个新的栈启动,且不影响 Application 的其他 Activity 。(详情请看 Tasks and Back Stack 文档)
android:excludeFromRecents="true"作用:使该 Activity 不出现在最近任务中。
Example :
<activity android:name="com.example.notificationdemo.AloneActivity" android:taskAffinity="" android:excludeFromRecents="true" android:launchMode="singleTask" ></activity>
2. 构建并发布 Notification 。
a . 创建 Intent 。
b . 设置在新的 Task 中打开 Activity 。设置 Intent 的 Flag 为 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_CLEAR_TASK
c . 设置 Intent 的其他选项
d . 构建 PendingIntent
Example :
NotificationCompat.Builder builder = new Builder(getActivity()); builder.setContentTitle("NotifictionDemo") .setContentText("i am 多啦a梦?") .setSmallIcon(R.drawable.littlicon); Intent intent = new Intent(getActivity(), AloneActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pendingIntent = PendingIntent .getActivity(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent); NotificationManager mNotificationManager = (NotificationManager) getActivity() .getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(mId, builder.build());
- Notification中显示进度条
我们应该也都看过下载时在 Notification 显示的下载的进度条,看完这部分,你也可以做到。
我们可通过调用 NotificationCompat.Builder .setProgress () 方法把 progress bar 添加到你的 Notification 中,然后发布该 Notification 即可。实现原理为:更新带有新的进度的 Notification 。即可实现该效果。
注: android4.0 以上通过 setProgress 方法实现进度条显示,而 4.0 前的版本需要实现自己的 Notification layout 才可以。
同时,进度条也分为两种形式。
1. 知道当前的进度(如下载)
2.不知道当前进度(如安装应用程序)。
1. 显示知道进度的 progress bar
方法:调用 setProgress 方法设置最大进度,当前进度,然后发布 Notification 。
当进度完成后,你可以移除 progress bar ,也可保留。但一般来说,当进度完成时,都需要去更新 Notification 的内容。如设置 title 为下载完成。移除 progress 的方法为: setProgress(0,0,false)
Example:
private void sendFixProgressNotifiction() { final NotificationCompat.Builder builder = new NotificationCompat.Builder( getActivity()); builder.setContentTitle("正在下载").setContentText("下载进度") .setSmallIcon(R.drawable.littlicon); final NotificationManager notificationManager = (NotificationManager) getActivity() .getSystemService(Context.NOTIFICATION_SERVICE); new Thread(new Runnable() { @Override public void run() { int progress = 0; for (; progress <= 100; progress += 10) { builder.setProgress(100, progress, false); notificationManager.notify(321, builder.build()); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } builder.setContentText("下载完成"); builder.setProgress(0, 0, false); notificationManager.notify(321, builder.build()); } }).start(); }
调用效果如图:
2. 不知道进度的 progress bar
仅仅是 progress bar 的一些 ui 的差别而已。该 progress bar 就是一个动画,它持续运动,直到我们移除该动画。
与前面 progress bar 的不同之处:
调用方法Builder.setProgress(0,0,true)而不是Builder.setProgress(max,progress,false);当第三个参数设置为true时会忽略前两个参数,因为根本不需要知道它们的值。
只需修改上面的例子中的
为:builder.setProgress(100, progress, false);
这样就可以了。builder.setProgress(0, 0, true);
- Heads-up Notification
引进自android 5.0.当对应级别的notification出现,而且手机处于活动状态(亮屏+解锁)时出现。
1. 用户正处于一个全屏模式
2.Notification 的 Priority 级别 高 而且有铃声 和震动(不管是否全屏都可以)
------学习自google官方guide文档-----Notifications