活力无限(第 1 部分):使用磁贴、徽章和 Toast

动态磁贴以及徽章、Toast 通知和推送通知的相关功能是 Windows 8 和 Windows 应用商店应用最显著的特点之一。它们相互结合,共同打造出了一个“活力无限”的系统:即使是在应用未运行的时候,应用仍可不断获得来自其各自服务的信息,这些信息将显示于“开始”屏幕和锁屏中。

本博客此前发布的数篇博文中已经介绍了一些涉及动态磁贴和通知的基本要素。

如果您希望回顾这些博文,请参阅:

为了基于这些资源进行构建,本篇由三个部分组成的博文将对几个方面的内容进行深入的介绍。

在第 1 部分(本博文)中,我们将介绍:

  • 概述用户体验的视觉之旅:“活力”对于用户而言意味着什么?
  • 磁贴、徽章和 Toast 通知的 XML 架构可以展示无法在模板目录中始终显而易见的多项特性和功能。
  • 磁贴、通知和后台任务的关系。

第 2 部分将探讨如何以多种语言编写和调试服务,特别是采用本地主机和面向 Web/Visual Studio 2012 的 Visual Studio 2012 Express 进行编写和调试。第 2 部分还将涉及专为此目的而使用 Windows Azure 移动服务的内容。

第 3 部分将探讨推送通知的主题。这包括如何使用 Windows 推送通知服务 (WNS),以及如何使用 Windows Azure 移动服务来支持您应用中的推送通知。

这三部分与我在 //Build 2012 上所做的发言:3-101 活力无限(此视频和幻灯片平台已发布于 Channel 9)相互呼应,并扩展了相关内容。这三部分也反映和扩展了我在 Microsoft Press 中的免费电子书的第 13 章的内容:使用 HTML、CSS 和 JavaScript 编程 Windows 8 应用(尽管该标题标明了三种特定语言,但是该内容对于使用其他语言编程的开发人员同样有所帮助)。

“活力”对于用户而言意味着什么?

我们在本系列中所讨论的“活力”出现于用户所能见到的三个地方:“开始”屏幕、锁屏,以及其他任何显示 Toast 通知的位置。

相信到目前为止,您已经非常熟悉“开始”屏幕上磁贴的创意。如以下示例所示,磁贴能以方形和宽形呈现,并包含多种显示文本、图像,或二者组合的布局模板。应用的清单将定义磁贴的颜色,只要应用能够同时支持方形和宽形磁贴,用户即可任意选择形状。磁贴的左下角能够显示应用名称、徽标,或不显示任何内容。而磁贴的右下角可包含一个小型“徽章”,这可以是从 1 到 99 的任意数字(来作为邮件、消息等内容的数量),或是一些预定义的字形(请参阅徽章图像目录)。

Windows 8“开始”屏幕显示的磁贴

磁贴模板还包括大量“扫视”设计,该设计能够让用户在诸如图像等一部分内容和诸如文本等第二部分内容间翻转(在磁贴模板目录中,他们看起来像是双层磁贴,但是每一层只显示了一半)。系统将同步显示这两部分的切换动画效果和所有其他磁贴的动画效果。此外,每个磁贴能够将最多五个自动循环的更新排入队列,系统同样将与其他磁贴协调,为这些更新提供动画效果。队列中的每个更新将获得一个标记,因此您可为每个更新更换标记,否则队列将按照“先进先出”的方式操作。

不同动画效果之间的协调有助于我们理解 Windows 为何要将磁贴更新限制到一组预定义的模板中。这是因为,如果应用可对其磁贴进行任何所希望的操作,那么“开始”屏幕体验将是怎么样一番情形。此外,在磁贴上自由播放视频将更快地耗尽电池电量,因此这样“放任自由”必将导致混乱。没错,对于完全静止的“开始”屏幕,这并不会产生什么问题,但是观众却无法获得卓越的视觉效果!Windows 的设计人员希望您能长时间地享受“开始”屏幕,因此他们打造了一个活力无限,但又让所有磁贴统一、和谐的体验。使用模板和系统控制的动画效果能够提供一定的一致性,同时又允许各个应用之间存在较大的差异。(请记住,您可使用始终只包含图像的模板,并在其中放置您希望置于该处的任何设计,但是请避免创建诸如按钮等可引发磁贴不同部分的不同行为的图像,系统将不支持此类设计。)

Toast 通知将显示于“开始”屏幕、锁屏、桌面或任何运行的应用的顶部。点击 Toast 将激活其相关的应用(该应用中包含在系统发布 Toast 时指定的任何参数)。Toast 将以相关应用的清单所定义的颜色显示,并在右下角包含该应用的徽标;颜色和徽标都将有助于用户识别点击 Toast 所将激活的应用。

与磁贴相同,每个 Toast 的布局是由 Toast 模板目录中的模板所定义的,开发人员可在目录中选择仅包含文本或文本加图像的模板。Toast 将在显示一段时间后淡出,此过程可伴随以声音,并可作为会议提醒反复出现。

Toasts 将在显示一段时间后淡出。

锁屏中,应用活动将与时间、日期和系统徽章并排显示。正如以下示例所显示的,应用内容由位于底部的最多七个徽标和徽章,以及显示于时间旁边的一个文本更新组成:

本应用内容包括最多 7 个徽标和徽章,以及一个显示于时间旁边的文本更新

用户可通过“PC 设置”>“个性化”>“锁屏”来控制显示于锁屏中的内容,以下显示了一个示例。在第一行中,点击一个方形按钮将列出支持锁屏功能,并将显示为徽标和徽章的一组应用。在第二行中,您可选择将提供详细文本的应用。该文本将专门显示该应用的最新磁贴更新内容。

支持锁屏的应用列表

更新 XML

现在,我们已经了解何谓用户体验活跃,那么接下来的问题是:这些更新究竟是由什么组成的?即什么将用于描述磁贴更新、徽章或 Toast 通知?

除了我们所说的“原始”通知以外,所有更新都是一组用于更新磁贴或显示 Toast 的 Windows 能够处理的 XML。(原始通知能够包含应用特定的文本或二进制数据。接收这些通知的应用或后台任务通常将处理该数据并发布磁贴更新、徽章更新或响应 Toast。)

我们一直提到的模板就是这些更新的特定 XML 结构。例如,数字 7 的徽章更新如下:

 <badge value="7"/>

作为经常调用的 XML 结构,以下显示的是我们此前所看到的位于中下方的磁贴的红点徽章的类似负载。

 <badge value="busy"/>

包含图像、文本以及徽标/名称选项引用,并使用 TileWideSmallImageAndText01 模板的同样宽度的磁贴的 XML 负载大致如下(图像 URI 是虚构的):

 <tile>
  <visual>
    <binding template="TileWideSmallImageAndText01" branding="logo">
      <image id="1" src="https://friends.contoso.com/sally.png" alt="Sally's picture"/>
      <text id="1">Hey, you there? Txt me when you’re back</text>
    </binding>
  </visual>
</tile>

在此负载中,您可以看到我们识别了 binding 元素中的模板。Windows 将根据模板验证 XML 的其他部分。binding 元素的 branding 属性指示了是显示徽标、应用的名称,还是不显示任何内容。binding 的子级元素随后将描述该模板的其他必要部分。

现在,过多关注此类更新的特定模板没有太多意义,而是应该关注其通用的 XML 架构,因为这些架构将揭示可在各个更新中使用的其他功能。也就是说,磁贴模板目录徽章图像目录,以及 Toast 模板目录仅显示了要求的元素、架构,另一方面,其还显示了所有额外的选项。

架构内容记录于该文档的磁贴、Toast 和徽章架构部分。但是,详细内容可能分散于许多单独主题中,因此让我将这些内容汇集到“伪架构”中,伪架构可让我们从整体检查结构。

最简单的是徽章更新的结构,因此让我们从这开始说起:

 <?xml version="1.0" encoding="utf-8" ?>
<badge value = "1-99" | "none" | "activity" | "alert" | “attention” | "available" |
    "away" | "busy" | "newMessage" | "paused" | "playing" | "unavailable" | "error" 
    version? = "integer" />

从技术角度来说,所有 XML 负载都应该有 <?xml> 头标记;在没有这些头标记的情况下,Windows 仍可正常运行,但是为了确保完整性,我希望仍然将其包括其中。

接下来,您可看到该 badge 元素仅包含一个 value 属性,该属性可以是一个数字(大于 99 的任何数字将显示为“99+”),或是一组可识别特定字形的预定义字词。这些内容还记录于本文档的徽章图像目录页面。

其他唯一的属性是可选的 version(名称后的 ? 代表可选),该属性可让开发人员在今后更改架构。由于这是可选属性,因此目前您可在您的负载中将其省略。

磁贴更新具有以下伪架构:

 <?xml version="1.0" encoding="utf-8" ?>
<tile>
  <visual version? = "integer" lang? = "string" baseUri? = "anyURI" fallback? = "string"
    branding? = "none" | "logo" | "name" addImageQuery? = "boolean" >

    <!-- One or more binding elements -->
    <binding template = "TileSquareImage" | "TileSquareBlock" | "TileSquareText01" | ... 
      fallback? = "string" lang? = "string" baseUri? = "anyURI"
      branding? = "none" addImageQuery? = "boolean" >
      
      <!-- Some combination of image and text elements -->
      <image id = "integer" src = "string" alt? = "string" addImageQuery? = "boolean" />
      <text id = "integer" lang? = "string" />
    </binding>
  </visual>
</tile>

visual 元素包含可整体应用到更新的属性,在该元素中,我们能够看到可选的 version 属性,目前您可再次将其省略。其他属性如下所述:

属性

描述

lang

一个可选的 BCP-47 语言字符串,该字符串将识别更新的数据的语言,例如“en-US”或“de-DE”。

baseUri

一个可选的 URI,您可为负载中的所有其他 URI 而预置该 URI,从而让您在建造负载时省略这些冗余的信息。默认值为“ms-appx:///”。

branding

指示是在磁贴上显示应用的徽标(默认情况为“logo”),其名称(“name”),还是不显示任何内容(“none”)。

addImageQuery

如果将其设置为“true”(默认情况为“false”),则指示 Windows 向负载中的 URI(即图像 URI)所发出的每个请求追加查询参数,以识别当前语言、比例因子和对比度设置。参数形式为:

?ms-scale=<scale>&ms-contrast=<contrast>&ms-lang=<language>

有关详情,请参阅磁贴和 Toast 通知的全球化和可访问性

在 visual 内,负载随后将拥有一个或多个 binding 元素,其中每个磁贴尺寸一个元素。也就是说,一个单一负载能够(而且理想情况下应该)同时包含一个面向方形和宽形磁贴的更新,由于用户可能随时更改磁贴尺寸,因此这一点十分重要。如果您省略了某一尺寸或另一尺寸,那么在用户将磁贴设置为特定尺寸时,则不会显示该更新的任何内容。但是,请务必注意,您可以为不同的尺寸单独发送更新,Windows 将保留二者。

在 binding 内,您可以看到 template 识别出了需要验证的 XML 模板,另外,您可以看到 visual 中也存在相同的属性,除非它们仅适用于本 binding 中的属性(并覆盖 visual 中的这些属性)。另一属性是 fallback,该属性可识别系统在无法找到主模板时所使用的模板。该属性将在今后用于向后兼容,因此您无需将其与 Windows 8 一同使用。

在各个 binding 中,根据模板的不同,可能存在一些 image 和 text 元素的组合;我相信您从这些元素的名称中就能了解其属性,或者我已在此前介绍过其属性。请注意,正如您所预期的,image 或 text 中(也可能出现在 binding 或 visual 中)的任何属性都将覆盖父级元素中的属性值。

对于 Toast 通知,磁贴的结构较为相似,但是其包含一些其他特性:

 <toast launch? = "string" duration? = "long" | "short" >
  <visual version? = "integer" lang? = "string"
    baseUri? = "anyURI" branding? = "none" | "name" | "logo" addImageQuery? = "boolean" >

    <!-- One or more bindings -->
    <binding template  = "ToastImageAndText01" | "ToastImageAndText02" | ...=""
      fallback? = "string"  lang? = "string" baseUri? = "anyURI"
      branding? = "none" addImageQuery? = "boolean" >

      <!-- Some number of child elements -->
      <image id  = "integer" src = "string" alt = "string" addImageQuery? = "boolean" />
      <text id = "integer" lang? = "string" />
    </binding>
  </visual>

  <!-- Optional audio -->
  <audio src? = "ms-winsoundevent:Notification.Default" | ...=""
    loop? = "boolean" silent? = "boolean" />
</toast>

visual 内的 lang、baseUri、branding 和 addImageQuery 属性具有相同的面向磁贴的含义和默认值,这与 binding、image 和 text 属性内的所有属性相同。在负载的这一部分,磁贴更新和 Toast 通知的唯一真正的差别在于受支持的模板。

Toast 负载的不同之处在于最外层的 Toast 元素的属性,及其可选的 audio 子级。

借助 toast,launch 属性可被分配一个字符串,该字符串将作为参数被传递到应用的激活处理程序,这与辅助磁贴将发生的情形一模一样。duration 属性将获得“short”值(五秒或从“PC 设置”>“轻松访问”中获得的值)或“long”值(25 秒或从“PC 设置”>“轻松访问”中获得的值,选择较长的值)。

在 audio 中,其 src 属性是一个字符串,该字符串将指示来自 Toast 音频选项目录的一组预定义声音中的一个声音。目前,您只能从这些声音中选择,这些声音通常将映射到您在“控制面板”中所配置的任何系统声音中。(请注意:如果您像我通常所做的那样关闭所有声音,那么您将无法听到任何声音,请在测试应用时牢记这一点!)。存在该局限性的原因有几个。首先,包含来自远程源的自定义声音将产生更多的网络流量,这将在设备处于锁屏状态或试图在连接待机模式保存电量时引发令人担忧的问题。同时也可以防止可能发生的滥用行为,例如在 Toast 中包含音频广告。

此外,如果将 silent 属性设为“true”,那么系统将始终静音。而对于 loop,如果设置了 Toast 的 duration 属性,而且您将音频的 src 设置为目录中四个“循环”声音(“闹钟”和“呼叫”各两种变体)中的一种,那么您还可将 loop 设置成“true”以重复声音,或将其设置成“false”,而只播放一次声音,这也是默认设置。

除了循环播放音频,您还可计划重复执行的 Toast。这并不是 XML 负载中的一部分,而是您可在创建 ScheduledToastNotification 对象时指示的某个内容。在这些情形中,每个间隔将出现相同的负载(音频及全部)。

在不运行应用的情况下保持无限活力

了解了哪些 XML 负载将生成哪类更新后,需要解决的下一个问题是了解这些负载将如何在适当的时间进入系统,以及这些负载的创建方式。我们已在此前的博文《打造卓越的磁贴体验(第 1 部分)》和《打造卓越的磁贴体验(第 2 部分)》中探讨过这些主题,这两篇博文向您展示了如何在代码中生成负载。这包括使用通知扩展库,通知扩展库中包含大量示例,同时可通过 Visual Studio 作为 NuGet 包使用。

在此处,让我们集中总结一下提供这些负载的方法。发布这些负载共有三种方法:

  1. 运行的应用或应用的后台任务能够发布直接本地更新。这些操作可立即执行,也可计划在今后某个时间执行。磁贴、徽章和 Toast 也可包含一个过期时间,过了该时间后它们将被自动删除,或者如果在该时间之前它们未被提供,则它们将从计划中删除。

  2. 运行应用能够为 Windows 提供最多五个 URI,以进行定期更新,并指定范围从 30 分钟到一天不等的间隔。(当使用多个 URI 时,每个 URI 将对应于更新队列中的五个时间间隔中的一个。)一旦配置完定期更新后,Windows 将在每个间隔向 URI 发送一个请求 (HTTP GET)。如果 Windows 接收到返回的一个有效负载,那么 Windows 将以应用的名义把该更新发送到相应的磁贴,就像运行的应用直接发布该更新一样。我们将在本博文系列的第 2 部分来介绍如何创建更新服务。

    定期更新的主要优势在于即使是在应用未运行时,请求仍将继续,这可让磁贴在一段较长的时间内持续接收更新和徽章,而完全不需要用户启动应用。当然,我希望您的更新能够足够有趣,从而吸引用户再次使用您的应用!

  3. 应用能够请求一个 Windows 推送通知 (WNS) 渠道 URI,并将该 URI 发送到其自有的后端服务中。随后,这些服务可以借助通过 WNS 的该渠道 URI 来发出任何特定类型的更新,而这样可以在特定设备联机时把该更新发送到该特定设备。Windows 将接收这些更新,并将其应用到相应的磁贴或显示 Toast。此外,应用能够配置一个后台任务来接收这些推送通知(原始通知就需要进行该操作)。我们将在本博文系列的第 3 部分探讨推送通知。

以下表格总结了这些选项,并包含了磁贴的周期队列特性,以及 Toast 的重复执行/音频功能:

通知类型

队列

已计划

即将过期

重复执行

音频

定期

推送

磁贴

   

徽章

   

   

Toast

 

 

原始

           

请注意,您在此处看到的有关磁贴和徽章的所有内容同样适用于应用的主磁贴和辅助磁贴。以上所引用的此前的博文详细介绍了有关辅助磁贴的内容。您也可参阅辅助磁贴示例了解相关内容。

说到示例,让我再向您介绍一下应用磁贴和徽章示例计划通知示例,以及推送和定期通知客户端示例,从而让您查看所有不同应用场景下的完整示例。为了更好地使用您应用中的各种磁贴和通知,这些示例中的代码非常值得您抽空来熟悉一下。

除此之外,还请记住后台任务也可发布磁贴、徽章和 Toast 更新。我喜欢将后台任务理解成是一种应用代码类型,这些代码即使是在应用本身挂起或完全不处于内存中时仍可运行。从后台任务发布更新所使用的代码与主应用所使用的代码相同,因此此处并无实际差别。

后台任务很适于检查不同条件的状态,整个过程十分迅速,因此能够遵循分配给这些任务的 CPU 配额。当情况需要时,后台任务可生成适当的通知。事实上,后台任务的主要操作是 (a) 发布此类更新,或 (b) 将值保存到应用的 AppData 文件夹或设置容器中,应用将在其下次运行时处理这些文件夹或容器。

后台任务还是应用在未运行时处理原始推送通知所必不可少的,我们将在本博文的第 3 部分中来探讨这一话题。

有关后台任务的更多内容,请参阅本博客此前的博文《在后台高效工作》,以及更一般的概述《当应用程序在屏幕外时保持高工作效率》。

了解了这些内容之后,那么我们就已经准备好告别熟悉的客户端应用内容,并跟随本博文的第 2 部分和第 3 部分,一同了解包含您的磁贴、徽章和 Toast 的在线服务所扮演的重要角色。

Kraig Brockschmidt

Windows 生态系统团队项目经理

使用 HTML、CSS 和 JavaScript 编程 Windows 8 应用作者