From scratch - the system in-depth study android (practice - let's start writing code -Android framework for learning -7 notice) ...

 

Chapter 7 notification

A notification message is displayed on a screen he is outside of your application. When you tell the system you want to publish a notice, it first appears as an icon in the notification area. To see the details of the notification, the user can click on the notification area launched a new interface. Let's look at Figure 7-1 and Figure 7-2:

 

Figure 7-1 notification appears in the notification area

 

FIG effect after 7-2 notifies the expansion (Drawer)

Note: Unless otherwise stated in this chapter are references to the NotificationCompat.Builder, it v4 Support Library has formally added to the API Level 15. But with low v4 Support Library version of the system can also be used. In addition Notification.Builder added to android3.0.

7.1 notification display elements

Notice there are two visual styles, depending on the version and status of drawer:

Standard view

In the standard view of the notification drawer

Large view

A larger view. This view is a part of the notice of extension, this feature was added to android 4.1.

7.1.1 normal view

A generally high standard view 64dp. Even if you create a great view style, until it unfold before him still appear in the standard view. Figure 7-3:

 

FIG notification of 7-3 under standard view

The following is a description of each section:

1. Content title

2. Large icon

3. Content text

4. Content info

5. Small icon

6. Published notice. You can use setWhen () to set a definite value.

7.1.2 Large view

When the notification is expanded, large-scale view appears and displays, generally expanded by the user using gestures, notification drawer will be expanded. Expand the notification available on android 4.1. Shown in Figure 7-4:

 

7-4 large notice type of view

注意大型View大部分的视觉元素与正常的视图共享。仅仅不同的地方是编号为数字7的地方,这个细节区域。各大View风格设置有些不同。可用的风格有:

Big picture style

细节区域包含一个256dp高度的bitmap在它的细节部分。

Big text style

在细节部分显示一个大型文本块。

Inbox style

在细节部分显示文本行数。

下面是大型view可用,但标准view不可用的风格:

Big content title

允许你覆盖标准view的内容标题,使之出现在展开view中

Summary text

允许你在细节区域添加文本行数。

7.2 创建一个通知

你想在NotificationCompat.Builder对象中为通知指定UI信息和动作,就必须先使用 NotificationCompat.Builder.build()来创建通知,这个方法会返回一个Notification对象,为了发布通知,你 可以通过调用NotificationManager.notify()来传递Notification对象到系统中。

7.2.1必须的通知内容

一个Notification对象必须包含以下内容:

通过setSmallIcon()设置一个小的icon

通过setContentTitle()来设置一个标题

通过setContentText()来设置细节文本

7.2.2可选的通知的内容和设置

所有其他通知设置和内容都是可选的,具体可参考API NotificationCompat.Builder类

7.2.3通知动作(action)

虽然它们是可选的,你应该至少添加一个动作到你的通知中。一个动作允许用户直接从通知到一个你应用程序的Activity中。一个通知能提供多个动 作。你应该总是定义一个动作,当用户点击通知时,触发它。通常这个动作打开一个你应用程序中的Activity。你也能添加按钮到通知中(Android 4.1中加入的新功能),用来执行额外的动作,如一个警告或即时响应的文本消息。如果你使用附加的动作按钮,你必须让他们的功能在一个Activity中 可用。在通知里面,这个动作通过PendingIntent来定义,请使用NotificationCompat.Builder中合适的方法来创建。例 如,当用户在Drawer中点击通知文本的时候,你想要启动Activity,你就可以通过调用setContentIntent()来添加一个 PendingIntent。用户点击通知启动一个Activity是最常见的情况。请记住在Androird4.1或更高版本中,你才能从一个动作按钮 中启动一个Activity。

7.2.4 创建一个简单的通知

以下代码片段是一个简单的例子,当一个用户点击通知时会打开一个activity。注意此段代码创建一个TaskStackBuilder对象并使用它创建一个PendingIntent。如代码清单7-1所示:

复制代码
NotificationCompat.Builder mBuilder =
        new NotificationCompat.Builder(this)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!");
Intent resultIntent = new Intent(this, ResultActivity.class);
 
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ResultActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(
            0,
            PendingIntent.FLAG_UPDATE_CURRENT
        );
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(mId, mBuilder.build());
复制代码

 

代码清单 7-1

7.2.5 应用一个大型的view风格到通知中

当一个通+知展开后出现一个大型的view,首先创建一个你想要的NotificationCompat.Builder对象。然后调用 Builder.setStyle()传入大型view的风格对象。记住android4.1之前的版本是不可用的。当然后面我们会讲解如何兼容低版本。 下面代码清单7-2是在7-1上做了适当修改:

复制代码
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
    .setSmallIcon(R.drawable.notification_icon)
    .setContentTitle("Event tracker")
    .setContentText("Events received")
NotificationCompat.InboxStyle inboxStyle =
        new NotificationCompat.InboxStyle();
String[] events = new String[6];
inboxStyle.SetBigContentTitle("Event tracker details:");
...
for (int i=0; i < events.length; i++) {
 
    inboxStyle.addLine(events[i]);
}
mBuilder.setStyle(inBoxStyle);
...
复制代码

 

代码清单 7-2

7.2.6 处理兼容性

并不是所有通知功能都用于特别的版本。例如动作按钮,依赖于展开的通知,它只出现于android 4.1和高版本中。因为只有在这个版本上展开的通知才可用。为了确保最好的兼容性,请使用NotificationCompat及其子类创建通知,最好是 用NotificationCompat.Builder,此外当你实现一个通知,请遵循以下过程:

1. 不管用户使用什么系统版本,都应该提供通知所有的功能给所有用户,为了做到这一点,需要在一个activity中验证所有的功能可用。你可能想要添加一个 新的Activity。例如,如果您想要使用addAction()来控制停止和启动媒体播放,首先需要在一个Activity中实现这个控制。

2. 当用户点击通知时,确保所有用户点击后都能启动一个界面。我们需要为Activity创建一个PendingIntent。然后使用setContentIntent()把PendingIntent添加到通知中。

7.3 管理通知

当你需要为同一类型的事件多次处理一个通知时,你应该避免每次重新生成新的通知。你应该考虑更新先前的通知,不是改变一些值就是添加一些值。例 如,Gmail通知用户新的email已经收到了,并且未读消息会自增计数,其实就是没收到一个通知消息做了处理。这就是所谓的“堆叠”通知。

7.3.1 更新通知

通知当然是可以被更新,使用通知ID来更新它,调用NotificationManager.notify(ID, notification)即可。如果先前的通知仍然可见,系统会从Notification 对象的content中更新它。如果先前的通知已经 dismiss掉了,一个新的通知将被创建。下面的代码演示了一个通知更新并显示事件数量,如代码清单7-3所示:

 
复制代码
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());
...
复制代码

 

代码清单 7-3

上面那些代码运行后就会生成如图7-5所示的效果:

 

图7-5 在drawer中显示更新通知

7.3.2 移除通知

移除通知的方法如下:

1. 用户通过个人或“Clear All” dismiss通知

2. 用户点击通知并且你在创建通知的时候调用了setAutoCancel()方法

3. 你根据指定的通知ID调用cancel()方法。这个方法也删除正在进行中的通知

4. 你调用cancelAll(),它将删除你先前所有的通知

7.4 当启动一个Activity时保持导航

当你从一个通知中启动一个Activity的时候,你必须保存用户的语气导航体验。点击返回键将和点击Home键的效果一样。为了保存导航的用户体 验,你应该在一个新的任务中启动Activity。根据给定的新任务如何设置PendingIntent取决于你启动的Activity的性质。通常有两 种情况:

1. 常规activity

正常启动Activity的情况下,设置PendingIntent来启动一个新的任务,并给PendingIntent提供一个后台堆栈,以复制 应用程序正常点击Back键的行为。从Gmail APP中来演示这个通知。当出现一条信息时你点击通知,就会看到信息本身。当你点击Back键时你会通过Gmail回退到Home屏幕,就像你已经进入了 Gmail,从Gmail退到Home屏幕一样。

2. 特别的activity

这种Activity,是在某种意义上Activity扩展了通知提供的信息,因为很难显示在通知本身。在这种情况下,设置 PendingIntent启动一个新的任务。没有必要创建一个后台堆栈,因为这个Activity并不是属于应用程序正常流程下的一部分。点击Back 键后依然会显示Home屏幕。

7.4.1 通过PendingIntent设立一个规则的activity

1. 在manifest中定义你应用程序的Activity层级。

◆支持Android 4.0.3和更早期的版本。在<activity>节点下添加子节点<meta-data>。表示父Activity与子Activity的关系。在<meta-data>节点下设置

android:name="android.support.PARENT_ACTIVITY"

android:value="<parent_activity_name>"

◆支持Android4.1和更高的版本。在<activity>节点中添加android:parentActivityName属性

完美支持的xml代码如代码清单7-4所示:

复制代码
<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 4.1和更高版本 -->

android:parentActivityName=".MainActivity">

<!—android 4.0.3和更早版本 -->

    <meta-data 

        android:name="android.support.PARENT_ACTIVITY"

        android:value=".MainActivity"/>

</activity>
复制代码

 

代码清单 7-4

2. 创建一个后台推栈基于Intent启动的Activity:

◆创建Intent来启动Activity

◆通过调用TaskStackBuilder.create()来创建一个任务栈

◆通过调用addParentStack()把后台推栈添加到栈中。对于你在manifest中定义的每一个Activity层级,后台堆栈都包含 一个启动Activity的Intent对象。并且这个方法还添加了标记(flag)来启动新任务中的堆栈。注意:尽管addParentStack() 的参数是一个启动Activity的引用,但这个方法实际并没有添加Intent进去。

◆通过调用addNextIntent()来添加Intent对象。它添加的对象就是最上面◆创建的那个intent对象。

◆如果你需要在堆栈上添加参数到Intent对象你可以调用TaskStackBuilder.editIntentAt()。这有时候是必要的, 当用户使用back键导航回来,以确保目标Activity显示有意义的数据。

◆调用getPendingIntent()获得一个PendingIntent。然后你能调用setContentIntent()把这个PendingIntent作为参数。

下面的代码片段演示了这个过程,如代码清单7-5所示:

复制代码
...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// 添加后台堆栈
stackBuilder.addParentStack(ResultActivity.class);
// 添加Intent到栈顶
stackBuilder.addNextIntent(resultIntent);
// 获得一个PendingIntent包含整个后台堆栈 containing the entire back stack
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());
复制代码

 

代码清单 7-5

7.4.2 通过PendingIntent设立一个专用的activity

以下部分描述了怎样通过PendingIntent设置一个专用的activity。

一个专用的Activity 不需要后台栈,因此你不一定要在manifest中定义它的Activity层级,并且你不必调用addParentStack() 来构建一个后台栈。 反而使用manifest设置Activity的任务选项,并通过调用getActivity()创建PendingIntent: 

1. 在manifest中添加以下属性到<activity>节点中。

◆android:name="activityclass"

完整的类名

◆android:taskAffinity=""

于代码中设置的FLAG_ACTIVITY_NEW_TASK 标记相结合,它确保这个activity不能进入应用程序的默认任务中。

◆android:excludeFromRecents="true"

从Recents排除了新的任务,以便用户不会意外导航回它。

如代码清单7-6所示:

复制代码
<activity
    android:name=".ResultActivity"
...
    android:launchMode="singleTask"
    android:taskAffinity=""
    android:excludeFromRecents="true">
</activity>
...
复制代码

 

代码清单 7-6

2. 构建和发布通知

◆创建一个Intent来启动Activity

◆设置Activity启动在一个新的、空的任务中,通过setFlags()方法来处理,传入FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TASK

◆为Intent设置其他需要的选项

◆通过getActivity()从Intent中创建一个PendingIntent。你能使用这个PendingIntent对象,把他作为参数传到setContentIntent()中

如代码清单7-7所示:

复制代码
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
Intent notifyIntent =
        new Intent(new ComponentName(this, ResultActivity.class));
notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent notifyIntent =
        PendingIntent.getActivity(
        this,
        0,
        notifyIntent
        PendingIntent.FLAG_UPDATE_CURRENT
);
 
builder.setContentIntent(notifyIntent);
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
复制代码

 

代码清单 7-7

7.5 显示通知的进度

通知可以包括一个动画进度指示器显示用户正在运行的操作的状态。如果你能估计这种操作需要花费多长时间,可以使用"determinate"形式的指示器(一个progress bar)。如果你不能估计花费的时间,使用“indeterminate”形式的指示器。

7.5.1 显示一个固定的时间进度指示器

显示一个确定的进度条, 通过调用setProgress()添加bar到你的通知中,setProgress(max, progress, false),然后发出通知。如代码清单7-8所示:

复制代码
...
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;
           
            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");
                        }
            }
            
            mBuilder.setContentText("Download complete")
            
                    .setProgress(0,0,false);
            mNotifyManager.notify(ID, mBuilder.build());
        }
    }
).start();
复制代码

 

代码清单 7-8

图7-6则是运行后的效果

 

图7-6 通知中progress bar运行的效果

7.5.2显示一个持续的Activity指示器

为了显示不确定的activity指示器,使用setProgress(0, 0, true)添加它到你的通知中,前面两个参数可以忽略,然后发出通知。它的结果是一个指示器,具有和进度条相同的样式,不同的地方就是它的动画是持续的。 在操作开始的地方就发出通知,这个动画将一直执行,直到你修改通知为止。将操作完成时,你应该手动调用setProgress(0, 0, false)然后更新通知移除activity指示器。如果你不这么做就算操作完成动画也会继续运行。下面让我们看下代码清单7-9:

mBuilder.setProgress(100, incr, false);
mNotifyManager.notify(0, mBuilder.build());

 

代码清单 7-9

运行后的效果如图7-7所示:

 

图7-7 持续的activity指示器动画

7.6 自定义通知布局

通知框架允许你自定义通知布局,它在一个RemoteViews 对象中定义了通知的外观。自定义布局通知和正常的通知类似,它们都是基于一个 RemoteViews定义在一个XML布局文件。自定义通知的可用高度取决于通知view的布局。正常view布局限制为64dp,展开view布局限 制为256dp。自定义通知布局,通过实例化一个RemoteViews对象然后inflates一个xml布局文件启动。不再调用 setContentTitle()方法,而使用setContent()方法来设置自定义通知的内容细节。使用这个方法在RemoteViews中来设 置view子类的值:

1. 为通知创建一个单独的xml布局文件。

2. 在你的应用程序中,使用RemoteViews方法来定义你通知的icon和文本。调用setContent()方法put这个RemoteViews对 象到你的NotificationCompat.Builder中。避免正在RemoteViews对象中设置Drawable背景,因为你的文本颜色可 能会变的看不清。

RemoteViews类也包括早期Chronometer或ProgressBar中的方法 ,更多详细信息请参考API文档。

当你使用自定义通知布局时,请特别注意不同的设备分辨率和水平方向上的问题。不要让你的自定义布局太复杂,一定要在各种配置中测试。

转载于:https://www.cnblogs.com/Codenewbie/articles/2973131.html

Guess you like

Origin blog.csdn.net/weixin_34148340/article/details/93448037