Microsoft Graph を使ってみよう : クロスデバイス エクスペリエンス (プロジェクト Rome)

# クロスデバイス エクスペリエンス (プロジェクト Rome)

現在、非常に多くの人が仕事やプライベートで複数のデバイスを使っています。朝はタブレットで新聞を読んだり、通勤中に携帯でメールをチェックもしますし、オフィスにつけば Mac や Windows PC で仕事をします。帰宅後は自宅のテレビで映画を見るかもしれません。

複数デバイスを使う生活が当たり前になる反面、デバイス間のデータの同期やアクティビティの同期をうまく行えないと、各デバイスを使う際に余計な作業が増えていきます。Microsoft ではこのような問題を解決すべく様々なアプローチをとっていますが Microsoft Graph もこのような問題を解決する機能を提供します。

# アクティビティフィード

現在ユーザーが利用しているアプリケーションの操作状況を Microsoft Graph のアクティビティフィードに記録することで、ユーザーがデバイスを切り替えた際に、続きの作業をストレスなく継続できます。

## アクティビティとして登録すべき内容

アプリケーションは全て目的や動作が異なるため、開発者がどのような情報をアクティビティフィードに記録するか決める必要があります。

- どこまで観たかなど再生中の映画や音楽、コンテンツの情報を記録して他デバイスで続きを再生
- 他デバイスで継続して編集、参照すべきドキュメントはクラウドに配置
- 継続する必要がない作業については記録すべきでない
- 承認のように他のユーザーが続きを行うような作業は記録すべきではない

以下にアプリケーションのタイプごとに、どのようなアクティビティが記録できるかサンプルを紹介します。

- ドキュメントを操作するもの: 操作中のドキュメントと操作の詳細情報
- メディアを再生するもの: プレイリストやプログラムまたは単体コンテンツの操作履歴
- ゲーム: 保存しているゲームの状況や最新の記録
- ユーティリティ: 単一目的のためのアプリが多く、継続作業があまりないため、利用する必要が限られる
- ビジネス用: 現在作業中の情報や、状態を知りたいアイテムの情報

# アクティビティリソース

特定アプリケーションのアクティビティを表します。

## 主なシナリオ
- アクティビティの作成、置き換え、読み取り、削除
- 最近のアクティビティの取得

## アクティビティリソースの操作
いくつか代表的な操作を以下に紹介します。

**アクティビティの作成または置き換え**
作成、置き換えに関わらず固有のアクティビティ ID をパスに指定して実行します。

- activitySourceHost : アプリケーション用の固有ドメイン
- appDisplayName : アプリケーションの表示名
- activationUrl : ネイティブアプリケーション起動で利用する URL
- fallbackUrl : ネイティブアプリケーションがない場合 Web で起動する URL
- visualElements : タイムラインに表示さえる UI 情報
- visualElements/content : タイムラインに表示されるアダプティブカードの定義
- historyItems : アクティビティが発生した履歴

詳細は [アクティビティリソースのプロパティ](https://developer.microsoft.com/ja-jp/graph/docs/api-reference/v1.0/resources/projectrome_activity#properties) と [VisualInfo リソースのプロパティ](https://developer.microsoft.com/ja-jp/graph/docs/api-reference/v1.0/resources/projectrome_visualinfo#properties)参照

PUT: https://graph.microsoft.com/v1.0/me/activities/myAppActivityId

```json:Body
{
    "appActivityId": "myAppActivityId",
    "activitySourceHost": "https://graph.microsoft.com",
    "userTimezone": "Asia/Tokyo",
    "appDisplayName": "MyApp.",
    "activationUrl": "https://developer.microsoft.com/ja-jp/graph/graph-explorer",
    "fallbackUrl": "https://developer.microsoft.com/ja-jp/graph/graph-explorer",
    "visualElements": {
        "attribution": {
            "iconUrl": "https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31"
        },
        "backgroundColor": "#ffffff",
        "displayText": "MyApp アクティビティテスト",
        "content": {
            "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
            "type": "AdaptiveCard",
            "body":
            [{
                "type": "TextBlock",
                "text": "MyApp タイムラインに表示されるタイトル",
                "weight": "bolder",
                "size": "medium"
            },
            {
                "type": "Image",
                "url": "http://adaptivecards.io/content/cats/1.png"
            }]
        }
    },
    "historyItems":[
        {
            "userTimezone": "Asia/Tokyo",
            "startedDateTime": "2018-05-20T10:00:00Z",
            "lastActiveDateTime": "2018-05-20T13:00:00Z",
        }
    ]
}
```

```csharp:C#
var activity = new UserActivity()
{
    AppActivityId = "myAppActivityId",
    ActivitySourceHost = "https://graph.microsoft.com",
    UserTimezone = "Asia/Tokyo",
    AppDisplayName = "Contoso, Ltd.",
    ActivationUrl = "https://developer.microsoft.com/ja-jp/graph/graph-explorer",
    FallbackUrl = "https://developer.microsoft.com/ja-jp/graph/graph-explorer",
    VisualElements = new VisualInfo()
    {
        Attribution = new ImageInfo()
        {
            IconUrl = "https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31"
        },
        Description = "MyApp アクティビティテスト説明",
        BackgroundColor = "#ffffff",
        DisplayText = "MyApp アクティビティテスト",
        Content = JObject.Parse(@"{
            '$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',
            'type': 'AdaptiveCard',
            'body':
            [{
                'type': 'TextBlock',
                'text': 'MyApp タイムラインに表示されるタイトル',
                'weight': 'bolder',
                'size': 'medium'
            },
            {
                'type': 'Image',
                'url': 'http://adaptivecards.io/content/cats/1.png'
            }]
        }")
    },
    HistoryItems = new UserActivityHistoryItemsCollectionPage()
    {
            new ActivityHistoryItem()
            {
                UserTimezone = "Asia/Tokyo",
                StartedDateTime = new DateTimeOffset(2018,5,20,10,0,0,new TimeSpan(9,0,0)),
                LastActiveDateTime = new DateTimeOffset(2018,5,20,13,0,0,new TimeSpan(9,0,0)),
            }
    }
};
var result = await graphClient.Me.Activities["myAppActivityId"].Request().UpdateAsync(activity);
```

実行すると Windows 10 のタイムラインには以下の情報が表示されます。タイルをクリックすると Graph エクスプローラーが起動します。

<img width="704" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/5d2a7880-7dbc-3c6c-371d-94b461688089.png">

**最近のアクティビティを取得する**

GET: https://graph.microsoft.com/v1.0/me/activities/recent

```csharp:C#
await graphClient.Me.Activities.Recent().Request().GetAsync();
```

# 履歴リソース

アクティビティの履歴です。

## 主なシナリオ
- 履歴の作成、置き換え、削除
 
## 履歴リソースの操作
いくつか代表的な操作を以下に紹介します。

**履歴の作成または置き換え**

作成の場合は新規の GUID、置き換えの場合は既存履歴の GUID をパスに指定。

PUT: https://graph.microsoft.com/v1.0/me/activities/{id}/historyItems/{history_guid}

```json:Body
{
    "startedDateTime": "2015-02-20T10:00:00+00:00",
    "userTimezone": "Asia/Tokyo",
    "lastActiveDateTime": "2015-02-20T20:54:04.3457274+00:00"
}
```

# デバイスに対する操作

現在ベータ版ではありますが、ユーザーが使っているデバイスに対する操作 API もあります。現在私の手元でテストできる環境がないためこのブログでの紹介はしませんが、是非ドキュメントをご覧ください。

# まとめ
既存のリソースをただ使う他のものと異なり、Microsoft Graph としての機能となります。今後クロスデバイスの体験はより重要性を増すため、モバイルアプリケーション開発をしている方は、是非こちらの機能を使ってください。

[目次に戻る](https://qiita.com/kenakamu/items/6a1ca508dc093779eefa)

# 参照

[クロスデバイスエクスペリエンス](https://developer.microsoft.com/ja-jp/graph/docs/api-reference/v1.0/resources/project_rome_overview)
[Microsoft Graph でのアクティビティフィード操作](https://developer.microsoft.com/ja-jp/graph/docs/api-reference/v1.0/resources/activity-feed-api-overview)
[ユーザー デバイスを一覧表示する (英語)](https://developer.microsoft.com/ja-jp/graph/docs/api-reference/beta/api/user_list_devices)
[デバイスのコマンドを送信する (英語)](https://developer.microsoft.com/ja-jp/graph/docs/api-reference/beta/api/send_device_command)
[デバイスコマンドの状態を取得する (英語)](https://developer.microsoft.com/ja-jp/graph/docs/api-reference/beta/api/get_device_command_status)
[アダプティブカード](http://adaptivecards.io/)