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效果展示

   

posted @ 2013-06-08 23:03  Innosight  阅读(200)  评论(0编辑  收藏  举报