Android倚天剑之Notification之城管三千
传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229
如果说足球是和平年代的战争,那么城管呢?伟大的人民曲艺家郭德纲先生曾经这样评价:借我城管三千,我能让世界和平!可见在当今社会中城管的威慑力有多大,尤其是中国的城管,你懂的^_^。本文欲借城管之名来引出Android平台对通知的管理也是十分强大的。话说世间尽是各种形态的“倚天剑”,如果没有法器能够降服它们,岂不是天下大乱。就像后羿射日的一样。各种样式的通知出现在通知抽屉中,怎么对它们进行有效的管理,让那些对用户有意义的通知出现在醒目之处,垃圾通知少出现或者根本就不出现,这样的设计才是实际意义的。本文旨在说明如何灵活运用通知这一把“倚天剑”,达到收发自如的境界。
1管理通知
当你需要为同一类型的事件多次处理一个通知时,应该避免每次都重复生成新的通知。相反,你应该考虑去更新先前的通知,无非是改变一些值或者添加一些值又或者两者都有。例如,Gmail通知用户收到新的邮件,并且未读消息会自增,其实就是对每收到一封邮件的通知消息做了处理。这就是所谓的“堆叠”通知。
1.1更新通知
通知当然是可以被更新的,使用通知ID来更新,需要调用NotificationManager.notify(ID, notification)方法即可。如果先前的通知依然可见,那么系统会直接从Notification对象的content中去更细;如果先前的通知已然不可见(dismiss),那么系统将创建一个新的通知。
1.1.1案例代码陈列
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // Sets an ID for the notification, so it can be updated 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; // Start of a loop that processes data and then notifies the user ... mNotifyBuilder.setContentText(currentText) .setNumber(++numMessages); // Because the ID remains unchanged, the existing notification is // updated. mNotificationManager.notify( notifyID, mNotifyBuilder.build()); ...
1.1.2案例效果展示
1.2移除通知
如果发生如下操作中的任一个,那么通知将不再可见:
用户通过个人或着“Clear All”来dismiss通知。
创建通知时调用了setAutoCancel()方法,用户点击通知。
根据指定的通知ID调用cancel()方法。该方法也能删除正在进行中的通知。
调用cancelAll()方法,它删除先前所有的通知。
2保存导航通知
当你从一个通知中开启一个Activity时,必须保存用户预期导航体验。点击Back键和点击Home键效果一样。点击最近应用列表应该显示作为一个单独任务的Activity。为了保存导航体验,你应该在一个新的任务中启动Activity。至于如何设置PendingIntent给你的新任务,那取决于你开启的Activity的性质。通常有两种情况:
2.1常规的activity
在正常启动Activity时,设置PendingIntent来启动一个新的任务,并给PendingIntent提供一个后台堆栈,以复制应用程序正常点击Back键的行为。以Gmail应用为例,当出现一条信息时你点击通知,会看到信息内容,然后点击Back键返回主屏。就跟你已经进入了Gmail,从Gmail返回主屏一样。2.1.1在manifest文件中定义你应用程序的Activity层级
<activity android:name=".NotiMainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 支持Android 4.1和更高的版本 设置android:parentActivityName --> <activity android:name=".NotiRegularActivity" android:parentActivityName=".NotiMainActivity"> <!-- 支持Android 4.0.3和更早期的版本 设置<meta-data> --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".NotiMainActivity" /> </activity>
2.1.2创建一个基于记录后台堆栈(用于复制应用程序正常点击Back键的行为)的Intent的PendingIntent
/** * 按应用中正常工作流程返回 * @return PendingIntent */ private PendingIntent backHeapStack() { return TaskStackBuilder.create(this) .addParentStack(NotiRegularActivity.class) .addNextIntent(new Intent(this, NotiRegularActivity.class)) .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); }
2.1.3创建和发布常规导航通知
Notification forwardRegularNoti = new NotificationCompat.Builder(this) .setContentTitle("Forward NotiRegularActivity") .setContentText("lynnli1229@gmail.com") .setSmallIcon(R.drawable.stat_notify_gmail) .setContentIntent(backHeapStack()) .build(); mNotiMgr.notify(FORWARD_REGULAR_NOTI_ID, forwardRegularNoti);
2.1.4效果展示
2. 2特别的activity
用户只会看到从一个通知中开启这种Activity。在某种意义上,如果需要提供的信息很难在通知上显示,就可以利用这种Activity来显示。在这种情景下,设置PendingIntent启动一个新的任务,没有必要创建一个后台堆栈。因为这种Activity并不属于应用程序正常流程下的一部分。点击Back键后依然会显示主屏。2.2.1在manifest文件的<activity>标签中添加activity的完整类名、加载模式、亲和力和从最近应用列表中排除(避免用户意外导航)等属性
<activity android:name=".NotiSpecialActivity" android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true" />
2.2.2创建一个基于在新、空任务中启动Activity的Intent的PendingIntent
/** * 直接返回主屏,不走应用正常工作流程 * @return PendingIntent */ private PendingIntent backHomeScreen() { Intent intent = new Intent(this, NotiSpecialActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); }
2.2.3创建和发布特别导航通知
Notification forwardSpecialNoti = new NotificationCompat.Builder(this) .setContentTitle("Forward NotiSpecialActivity") .setContentText("lynnli1229@gmail.com") .setSmallIcon(R.drawable.stat_notify_gmail) .setContentIntent(backHomeScreen()) .build(); mNotiMgr.notify(FORWARD_SPECIAL_NOTI_ID, forwardSpecialNoti);
2.2.4效果展示