デバイス間でもユーザーのアクティビティを継続する

このトピックでは、前回ユーザーがアプリで実行していた状態から再開できるようにする方法 (PC およびデバイス間で再開する場合にも対応) について説明します。

注意

2021 年 7 月から、Microsoft アカウント (MSA) を介して Windows デバイス間でアクティビティ履歴を同期しているユーザーには、タイムラインでの新しいアクティビティのアップロードのオプションがなくなりました。 引き続きタイムラインを使用して、ローカル PC でアクティビティ履歴 (最近使用したアプリ、Web サイト、ファイルに関する情報) を表示できます。 AAD 接続されたアカウントには影響はありません。

ユーザー アクティビティとタイムライン

私たちの毎日の時間は、複数のデバイス間に広がっています。 私たちは、バスの中でスマートフォンを、日中は PC を、夜は電話やタブレットを使用しています。 Windows 10 ビルド 1803 以降では、ユーザー アクティビティを作成すると、そのアクティビティが Windows タイムラインと Cortana の [ピックアップ] 機能に表示されます。 タイムラインは、ユーザー アクティビティを活用して作業していることを時系列に表示する豊富な機能を備えたタスク ビューです。 また、さまざまなデバイス間で作業していた内容も含めることができます。

Windows タイムライン イメージ

同様に、お使いの電話を Windows PC に接続すると、以前に iOS やAndroid デバイスで行っていた作業を続けることができます。

UserActivity は、ユーザーがあなたのアプリ内で作業していたことと考えてください。 たとえば、RSSリーダーを使用している場合、UserActivity はあなたが読んでいるフィードになります。 ゲームをプレイしている場合、UserActivity はあなたがプレイしているレベルになります。 音楽アプリを聴いている場合は、UserActivity があなたが聴いているプレイリストになります。 ドキュメントで作業している場合、UserActivity は作業を中断した場所になるなどです。 要するに、UserActivity は、ユーザーが自分のやっていることを再開できるように、アプリ内の目的地を表すものです。

UserActivity.CreateSession を呼び出して UserActivity を使用すると、システムは UserActivityの開始時刻と終了時刻を示す履歴レコードを作成します。 時間の経過とともに UserActivity を再使用していくと、複数の履歴レコードが記録されます。

アプリにユーザー アクティビティを追加する

UserActivity は、Windows でのユーザー エンゲージメントの単位です。 これには、アクティビティが属するアプリをアクティブ化するために使用される URI、ビジュアル、およびアクティビティを記述するメタデータの 3 つの部分があります。

  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 オブジェクトに必要なフィールドの最小セットを入力します。 ActivityIdActivationUri、および UserActivity.VisualElements.DisplayText
  3. UserActivity によって再アクティブ化できるように、カスタム スキーム ハンドラーをアプリケーションに追加します。

UserActivity はわずか数行のコードでアプリに統合できます。 たとえば、MainPage.xaml.cs の MainPage クラス内でこのコードを想像してみてください (注: 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から返されます。 その名前のアクティビティがなく、新しいアクティビティが New に設定された状態でUserActivity.State返される場合。
  • アクティビティがアプリに適用されます。 アクティビティ ID が他のアプリの ID と競合するのを心配する必要はありません。

UserActivity を取得または作成した後で、他の 2 つの必須フィールド、 UserActivity.VisualElements.DisplayTextUserActivity.ActivationUri を指定します。

次に、SaveAsync を呼び出して UserActivity を保存し、最後に CreateSession を保存します。これは UserActivitySession を返します。 UserActivitySession は、ユーザーが実際に UserActivity を使用しているときに、管理するために使用できるオブジェクトです。 たとえば、ユーザーがページを離れたときに UserActivitySession で を呼び出Dispose()す必要があります。 上記の例では、CreateSession() を呼び出す前に _currentActivity で` Dispose() を呼び出しています。 これは、ページのメンバー フィールドを作成 _currentActivity し、新しいアクティビティを開始する前に既存のアクティビティを停止する必要があるためです (注: ? は、メンバー アクセスを実行する前に null をテストする null 条件演算子 です)。

この場合、ActivationUri はカスタム スキームであるため、アプリケーション マニフェストにプロトコルを登録する必要もあります。 これは、Package.appmanifest XML ファイルで、またはデザイナーを使用して行います。

デザイナーで変更を加えるには、プロジェクトの Package.appmanifest ファイルをダブルクリックしてデザイナーを起動し、[宣言] タブを選択して、[プロトコル] 定義を追加します。 記入する必要がある唯一のプロパティは、現在、名前です。 上記で指定した URI の my-app と一致するはずです。

ここで、プロトコルによって起動されたときに何をすべきかをアプリに伝えるコードを記述する必要があります。 App.xaml.cs の OnActivated メソッドを上書きして、メイン ページに 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 
        } 
      ] 
    } 
  ]
}

以下のように、UserActivity に JSON 文字列としてアダプティブ カードのペイロードを追加します。

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 アカウントで認証されると、上記と同じデータを使用して アクティビティ オブジェクトと 履歴 オブジェクトを生成するための 2 回の単純な REST 呼び出しが必要です。

まとめ

UserActivity API を使用して、アプリをタイムラインと Cortana に表示させることができます。

キー API