即便跨设备,也继续用户活动

本主题介绍如何帮助用户恢复他们在电脑上的应用和跨设备执行的操作。

注意

从 2021 年 7 月开始,通过其 Microsoft 帐户 (MSA) 跨其 Windows 设备共享了活动历史记录的用户将无法再在时间线中删除新活动。 他们将仍可在其本地电脑上使用时间线并查看其活动历史记录(最近使用的应用、网站和文件的相关信息)。 AAD 连接的帐户将不受影响。

用户活动和时间线

我们每天的时间分布在多个设备上。 我们可能会在公共汽车上使用手机,白天使用电脑,然后在晚上使用手机或平板电脑。 从 Windows 10 内部版本 1803 或更高版本开始,创建 用户活动会使该活动 显示在 Windows 时间线和 Cortana 的“选取”功能中。 时间线是一个丰富的任务视图,它利用用户活动来显示你一直在处理的内容的时间视图。 它还可以包括跨设备正在处理的内容。

Windows 时间线图像

同样,将手机链接到 Windows 电脑允许你继续在 iOS 或 Android 设备上执行操作。

UserActivity 视为用户在应用中进行处理的特定内容。 例如,如果正在使用 RSS 阅读器,则 UserActivity 可能是正在读取的信息提要。 如果正在玩游戏,则 UserActivity 可能是正在玩的关卡。 如果正在使用应用听音乐,则 UserActivity 可能是正在收听的播放列表。 如果正在处理文档,则 UserActivity 可能是关闭处理文档的位置,等等。 简言之, UserActivity 表示应用中的目标,使用户能够恢复他们正在执行的操作。

通过调用 UserActivity.CreateSessionUserActivity 互动时,系统会创建一条历史记录,指示该 UserActivity 的开始时间和结束时间。 随着时间推移,重新参与该 UserActivity,系统会为其记录多条历史记录。

将用户活动添加到应用

UserActivity 是 Windows 中的用户参与单位。 它具有三个部分:用于激活活动所属的应用的 URI、描述活动的视觉对象,以及描述活动的元数据。

  1. ActivationUri 可用于恢复具有特定上下文的应用程序。 通常情况下,此链接采用两种形式:方案的协议处理程序(例如“my-app://page2?action=edit”)或 AppUriHandler(例如,http://contoso.com/page2?action=edit)。
  2. VisualElements 公开了一个类,该类允许用户使用标题、说明或自适应卡片元素直观地标识活动。
  3. 最后,内容是可以存储活动元数据的地方,而在特定上下文中,活动元数据可用于分类和检索活动。 通常,它采用 https://schema.org 数据的形式。

要向应用添加 UserActivity

  1. 当用户在应用中的上下文更改时,生成 UserActivity 对象(例如页面导航、新游戏关卡等)
  2. 使用最少的必填字段集填充 UserActivity 对象:ActivityIdActivationUriUserActivity.VisualElements.DisplayText
  3. 将自定义方案处理程序添加到应用,以便 UserActivity 可以重新激活它。

只需几行代码,UserActivity 即可集成到应用中。 例如,假设 MainPage 类中的MainPage.xaml.cs此代码(注意:假定 using Windows.ApplicationModel.UserActivities;):

UserActivitySession _currentActivity;
private async Task GenerateActivityAsync()
{
    // Get the default UserActivityChannel and query it for our UserActivity. If the activity doesn't exist, one is created.
    UserActivityChannel channel = UserActivityChannel.GetDefault();
    UserActivity userActivity = await channel.GetOrCreateUserActivityAsync("MainPage");
 
    // Populate required properties
    userActivity.VisualElements.DisplayText = "Hello Activities";
    userActivity.ActivationUri = new Uri("my-app://page2?action=edit");
     
    //Save
    await userActivity.SaveAsync(); //save the new metadata
 
    // Dispose of any current UserActivitySession, and create a new one.
    _currentActivity?.Dispose();
    _currentActivity = userActivity.CreateSession();
}

上述方法中的 GenerateActivityAsync() 第一行获取用户的 UserActivityChannel。 这是此应用的活动将发布到其中的信息提要。 下一行查询名为 MainPage的活动的通道。

  • 你的应用应以这样的一种方式命名活动,即每次用户在应用中的特定位置时都生成相同的 ID。 例如,如果应用基于页面,则请使用页面的标识符;如果文档基于文档,则请使用文档的名称(或名称的哈希)。
  • 如果源中存在具有相同 ID 的现有活动,则会从设置为“已发布”的UserActivity.State通道返回该活动。 如果没有具有该名称的活动,并且新活动将返回 UserActivity.State 并设置为 “新建”。
  • 活动的作用域限定在你的应用中。 无需担心你的活动 ID 与其他应用中的 ID 相撞。

获取或创建 UserActivity 后,指定其他两个必填字段:UserActivity.VisualElements.DisplayTextUserActivity.ActivationUri

接下来,通过调用 SaveAsync 保存 UserActivity 元数据,最后返回 UserActivitySession 的 CreateSession UserActivitySession 是用于管理用户实际参与 UserActivity 的时间的对象。 例如,当用户离开页面时,应调用 Dispose() UserActivitySession 。 在上面的示例中,我们还在调用前调用Dispose()_currentActivityCreateSession() 这是因为我们做了 _currentActivity 页面的成员字段,我们希望在启动新活动之前停止任何现有活动(注意: ? 执行 成员访问之前测试 null 的 null 条件运算符 )。

由于在这种情况下, ActivationUri 这是一种自定义方案,因此还需要在应用程序清单中注册协议。 此操作在 Package.appmanifest XML 文件中完成,或使用设计器完成。

要使用设计器进行更改,请双击项目中的 Package.appmanifest 文件以启动设计器,选择“声明”选项卡并添加“协议”定义。 目前,唯一需要填写的属性是“名称”。 它应与上面 my-app指定的 URI 匹配。

现在,我们需要编写一些代码,以便告诉应用在协议激活应用时该怎么办。 我们将重写 OnActivated App.xaml.cs中的方法,将 URI 传递到主页,如下所示:

protected override void OnActivated(IActivatedEventArgs e)
{
    if (e.Kind == ActivationKind.Protocol)
    {
        var uriArgs = e as ProtocolActivatedEventArgs;
        if (uriArgs != null)
        {
            if (uriArgs.Uri.Host == "page2")
            {
                // Navigate to the 2nd page of the  app
            }
        }
    }
    Window.Current.Activate();
}

此代码的作用是检测是否已通过协议激活应用。 如果是,则它会查看应用应该做些什么以便继续其被激活的任务。 由于是一个简单应用,此应用要继续执行的唯一活动是在应用启动时将你转至辅助页面。

使用自适应卡片改进时间线体验

用户活动显示在 Cortana 和时间线中。 当活动显示在时间线中时,我们使用自适应卡片框架显示它们。 如果未为每个活动提供自适应卡片,时间线将根据应用程序名称和图标、标题字段和可选说明字段自动创建一个简单的活动卡片。 下面是自适应卡片有效负载及其生成的卡片示例。

自适应卡片]

自适应卡片有效负载 JSON 字符串示例:

{ 
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", 
  "type": "AdaptiveCard", 
  "version": "1.0",
  "backgroundImage": "https://winblogs.azureedge.net/win/2017/11/eb5d872c743f8f54b957ff3f5ef3066b.jpg", 
  "body": [ 
    { 
      "type": "Container", 
      "items": [ 
        { 
          "type": "TextBlock", 
          "text": "Windows Blog", 
          "weight": "bolder", 
          "size": "large", 
          "wrap": true, 
          "maxLines": 3 
        }, 
        { 
          "type": "TextBlock", 
          "text": "Training Haiti’s radiologists: St. Louis doctor takes her teaching global", 
          "size": "default", 
          "wrap": true, 
          "maxLines": 3 
        } 
      ] 
    } 
  ]
}

将自适应卡片有效负载作为 JSON 字符串添加到 UserActivity ,如下所示:

activity.VisualElements.Content = 
Windows.UI.Shell.AdaptiveCardBuilder.CreateAdaptiveCardFromJson(jsonCardText); // where jsonCardText is a JSON string that represents the card

跨平台和服务到服务集成

如果应用运行跨平台(例如在 Android 和 iOS 上),或维护云中的用户状态,则可以通过 Microsoft Graph 发布 UserActivities。 使用 Microsoft 帐户对应用程序或服务进行身份验证后,只需使用两个简单的 REST 调用来生成活动和历史记录对象,即可使用上述相同数据。

总结

可以使用 UserActivity API 使应用显示在时间线和 Cortana 中。

关键 API