静的カード

静的カードを挿入、更新、読み取り、削除できるのは、シンプルな REST API です。また、ロケーションやメディアなどの静的カードにオブジェクトをアタッチできます。

仕組み

静的カードは、デフォルトで Glass の時計の右側に表示され、配信時にユーザーに関連する情報を表示します。ただし、ライブカードのように即時に対応する必要がないため、ユーザーは自分の時間に応じてカードを読み取ったり操作したりできます。

Glassware がタイムラインに静的カードを挿入すると、Glass はユーザーに警告する通知音を再生する場合があります。また、7 日が経過するか、または 200 枚の新しいカードがリリースされると、それまでの静的カードはすべて右にシフトしてタイムラインから削除されます。

アフィリエイト住所アセットの用途

静的カードは、重要なアクティビティが発生したときにユーザーに定期的な通知を配信する場合に適しています。たとえば、トップニュースをリアルタイムに送信するニュース配信サービスなどです。Mirror API の静的カードでは、OPEN_URI メニュー項目からライブカード没入型を開始することもできます。これにより、通知として静的カードを使用するライブ インタラクションを作成できるほか、ライブカードや没入型機能を使用して、さらにインタラクティブなエクスペリエンスを提供できます。

タイムライン アイテムで可能なオペレーションの一覧については、リファレンス ドキュメントをご覧ください。

静的カードの挿入

静的カード(タイムライン アイテム)を挿入するには、タイムライン アイテムの JSON 表現を REST エンドポイントに POST します。

タイムライン アイテムのほとんどのフィールドは省略可能です。最もシンプルな形式のタイムライン アイテムには、次の例のように短いテキスト メッセージのみが含まれます。

未加工の HTTP

POST /mirror/v1/timeline HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {auth token}
Content-Type: application/json
Content-Length: 26

{ "text": "Hello world" }

Java

TimelineItem timelineItem = new TimelineItem();
timelineItem.setText("Hello world");
service.timeline().insert(timelineItem).execute();

Python

timeline_item = {'text': 'Hello world'}
service.timeline().insert(body=timeline_item).execute()

成功すると、作成されたアイテムの完全なコピーを含む 201 Created レスポンス コードが返されます。上記の例では、成功したときのレスポンスは次のようになります。

未加工の HTTP

HTTP/1.1 201 Created
Date: Tue, 25 Sep 2012 23:30:11 GMT
Content-Type: application/json
Content-Length: 303

{
 "kind": "glass#timelineItem",
 "id": "1234567890",
 "selfLink": "https://www.googleapis.com/mirror/v1/timeline/1234567890",
 "created": "2012-09-25T23:28:43.192Z",
 "updated": "2012-09-25T23:28:43.192Z",
 "etag": "\"G5BI0RWvj-0jWdBrdWrPZV7xPKw/t25selcGS3uDEVT6FB09hAG-QQ\"",
 "text": "Hello world"
}

ユーザーのタイムラインに表示される挿入項目は、次のようになります。

添付ファイル付きのタイムライン アイテムの挿入

1 枚の写真は 1, 000 単語程度の価値があり、これはタイムラインの項目に収まらないものです。このために、タイムライン アイテムに画像や動画を添付することもできます。写真を添付したタイムライン アイテムを挿入する方法の例を次に示します。

未加工の HTTP

POST /upload/mirror/v1/timeline HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {auth token}
Content-Type: multipart/related; boundary="mymultipartboundary"
Content-Length: {length}

--mymultipartboundary
Content-Type: application/json; charset=UTF-8

{ "text": "A solar eclipse of Saturn. Earth is also in this photo. Can you find it?" }
--mymultipartboundary
Content-Type: image/jpeg
Content-Transfer-Encoding: binary

[binary image data]
--mymultipartboundary--

Java

TimelineItem timelineItem = new TimelineItem();
timelineItem.setText("Hello world");
InputStreamContent mediaContent = new InputStreamContent(contentType, attachment);
service.timeline().insert(timelineItem, mediaContent).execute();

Python

timeline_item = {'text': 'Hello world'}
media_body = MediaIoBaseUpload(
    io.BytesIO(attachment), mimetype=content_type, resumable=True)
service.timeline().insert(body=timeline_item, media_body=media_body).execute()

画像が添付されたタイムライン アイテムは、Glass で次のように表示されます。

動画を添付しています

タイムライン ファイルに動画ファイルを添付する場合は、ペイロード全体を一度にアップロードするのではなく、動画をストリーミングすることをおすすめします。Google Mirror API は、HTTP ライブ ストリーミング、プログレッシブ ダウンロード、リアルタイム ストリーミング プロトコル(RTSP)を使用したストリーミングをサポートしています。RTSP はファイアウォールによって頻繁にブロックされるため、可能な場合は他のオプションを使用してください。

動画をストリーミングするには、PLAY_VIDEO 組み込みメニュー アイテムを使用し、動画の URL をメニュー アイテムの payload として指定します。詳しくは、組み込みのメニュー項目を追加するサポートされているメディア形式をご覧ください。

ページ分け

1 つのタイムライン カードには収まらないものの、同じカードに関連付ける必要があるタイムライン アイテムは、ページ分けできます。ページ分けされたアイテムはすべて同じ timeline.id を共有するため、同じメニュー項目のセットを持ちます。ユーザーがページ分けされたタイムライン アイテムをタップすると、[詳細] メニュー項目が表示されます。

Glass は、text を表示するタイムライン アイテムを自動的にページ分けします。Glass で html のページ分けを自動的に行うには、次の例のように、クラスのプロパティを auto-paginate に設定した article タグを使用します。

<article class="auto-paginate">
 <h3>Very long list</h3>
 <ul>
   <li>First item</li>
   <li>Second item</li>
   <li>Third item</li>
   <li>Fourth item</li>
   <li>Fifth item</li>
   <li>Sixth item</li>
   <li>...</li>
 </ul>
<article>

手動でページ設定を行うには、各カードに表示するコンテンツに対して article タグを使用します。Glass では、各 article タグの内容を別のサブタイムライン カードに表示します。たとえば、次の HTML を使用してページ分けされたタイムライン アイテムを作成できます。

<article>
 <section>
   <p>First page</p>
 </section>
</article>

<article>
 <section>
   <p>Second page</p>
 </section>
</article>

<article>
 <section>
   <p>Third page</p>
 </section>
</article>

デフォルトでは、ページ分けされたタイムライン アイテムの最初のカードがカバーカードとして表示され、ユーザーが [もっと見る] メニュー アイテムを選択すると再び表示されます。[もっと見る] をタップした後、最初のカードが再び表示されないようにするには、最初の <article> タグで cover-only CSS クラスを指定します。

<article class="cover-only">
...

cover-only クラスは、自動ページ分けされるタイムライン アイテムもサポートしています。

<article class="auto-paginate cover-only">
...

分類

バンドルを使用して、関連する個別のアイテム(メールスレッド内の個々のメッセージなど)をグループ化できます。バンドルには、ユーザーがタップすると他のバンドルを含むサブタイムラインを表示するメインのカードがあります。通常のタイムライン カードと区別するため、バンドルのカバーカードの右上には、折り目が折りたたまれています。

タイムライン アイテムをバンドルするには、それらを bundleId に同じ値で作成します。最後に追加したアイテムは、バンドルのカバーカードです。

以下の画像は、バンドルのカバーカードで右上の隅に折りたたまれ、その下に 2 枚のバンドルカードを示しています。

タイムライン アイテムの読み取り

サービスは、作成したすべてのタイムライン アイテムと、共有されているすべてのタイムライン アイテムにアクセスできます。サービスに表示されるタイムライン アイテムを一覧表示する方法は次のとおりです。

未加工の HTTP

GET /mirror/v1/timeline HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {auth token}

Java

TimelineItem timelineItem = new TimelineItem();
service.timeline().list().execute();

Python

service.timeline().list().execute()

他の REST オペレーションを使用して、タイムライン アイテムを取得更新削除できます。

添付ファイルへのアクセス

タイムライン アイテムの添付ファイルには、attachments という配列プロパティからアクセスできます。その後、アタッチメントの contentUrl プロパティまたはアタッチメント エンドポイントを使用して、アタッチメントのバイナリデータを取得できます。

未加工の HTTP

GET /mirror/v1/timeline/{itemId}/attachments/{attachmentId} HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {auth token}

Java

TimelineItem item = service.timeline().get(itemId).execute();
String attachmentId = item.getAttachments().get(0).getId();
service.attachments().get(itemId, attachmentId).executeAsInputStream();

メニュー項目の作成

メニュー項目を使用すると、タイムライン カードに関連するアクションをリクエストできます。これには、組み込みメニュー項目とカスタム メニュー項目の 2 つのタイプがあります。

組み込みのメニュー項目を使用すると、Glass の特別な機能(タイムライン カードの読み上げ、特定の場所への移動、画像の共有、メッセージへの返信など)にアクセスできます。

カスタム メニュー アイテムを使用すると、アプリは Glassware に固有の動作を公開できます。また、ブランドに合わせてメニュー アイテム アイコンを指定することもできます。

組み込みのメニュー項目を追加する

組み込みのメニュー項目をタイムライン項目に追加するには、挿入時に menuItems array に指定します。 組み込みのメニュー項目を使用するには、各 menuItemaction に値を入力するだけです。

未加工の HTTP

HTTP/1.1 201 Created
Date: Tue, 25 Sep 2012 23:30:11 GMT
Content-Type: application/json
Content-Length: 303

{
  "text": "Hello world",
  "menuItems": [
    {
      "action": "REPLY"
    }
  ]
}

カスタム メニュー項目の定義

組み込みのメニュー アイテムがうまくいかない場合は、タイムライン アイテムの挿入または更新時に、以下の操作を行ってカスタム メニュー アイテムを独自に作成できます。

  • menuItem.action には CUSTOM を指定します。
  • menuItem.id を指定します。ユーザーがカスタム メニュー アイテムをタップすると、menuItem.id を含む通知が Glassware に送信されます。これにより、通知のソースを特定できます。
  • Glass に表示される iconUrldisplayName を追加するには、menuItem.values を指定します。iconUrl の背景が透明で、白色 50 x 50 の PNG 画像にカーソルを合わせます。
  • displayTime を指定します。displayTime を指定しない場合、ユーザーがカスタム メニュー アイテムをタップするたびにタイムライン アイテムがタイムラインの前に移動します。

未加工の HTTP

HTTP/1.1 201 Created
Date: Tue, 25 Sep 2012 23:30:11 GMT
Content-Type: application/json
Content-Length: 303

{
  "text": "Hello world",
  "displayTime": "2013-08-08T22:47:31-07:00",
  "menuItems": [
    {
      "action": "CUSTOM",
      "id": "complete"
      "values": [{
        "displayName": "Complete",
        "iconUrl": "http://example.com/icons/complete.png"
      }]
    }
  ]
}

ユーザーがタイムライン カードを固定できるようにする

ユーザーがタイムライン カードを固定するメニュー項目を作成できます。これにより、メインの時計カードの左側にタイムライン カードが常時表示されます。同じメニュー アイテムを使用してカードの固定を解除することもできます。

固定メニュー項目は組み込みのメニュー項目です。必要なのは、menuItemTOGGLE_PINNED action を指定することだけです。

未加工の HTTP

HTTP/1.1 201 Created
Date: Tue, 25 Sep 2012 23:30:11 GMT
Content-Type: application/json
Content-Length: 303

{
  "text": "You can pin or unpin this card.",
 "menuItems": [
    {
      "action": "TOGGLE_PINNED"
    }
  ...
 ]
}

登録チャンネル

Mirror API では、ユーザーがタイムライン アイテムで特定の操作を行ったとき、またはユーザーの位置情報が更新されたときに、通知に登録できます。通知に登録するときに、通知を処理するコールバック URL を提供します。

通知の受信

Mirror API からの通知は、JSON リクエスト本文を含むサブスクライブされたエンドポイントに POST リクエストとして送信されます。

未加工の HTTP

{
  "collection": "timeline",
  "itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "operation": "UPDATE",
  "userToken": "harold_penguin",
  "verifyToken": "random_hash_to_verify_referer",
  "userActions": [
    {
      "type": "<TYPE>",
      "payload": "<PAYLOAD>"
    }
  ]
}

Java

import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.mirror.model.Notification;

import java.io.IOException;
import java.io.InputStream;
// ...

public class MyClass {
  // ...

  /**
    * Parse a request body into a Notification object.
    *
    * @param requestBody The notification payload sent by the Mirror API.
    * @return Parsed notification payload if successful, {@code null} otherwise.
    */
  static Notification parseNotification(InputStream requestBody) {
    try {
      JsonFactory jsonFactory = new JacksonFactory();

      return jsonFactory.fromInputStream(requetBody, Notification.class);
    } catch (IOException e) {
      System.out.println("An error occurred: " + e);
      return null;
    }
  }

  // ...
}

Python

import json

def parse_notification(request_body):
  """Parse a request body into a notification dict.

  Params:
    request_body: The notification payload sent by the Mirror API as a string.
  Returns:
    Dict representing the notification payload.
  """
  return json.load(request_body)

エラーが発生しなかった場合は、サービスは API に 200 OK HTTP ステータス コードを返す必要があります。サービスがエラーコードで応答すると、Mirror API はサービスに通知の再送信を試みることがあります。

通知の種類

Mirror API はイベントごとに異なる通知ペイロードを送信します。

返信

ユーザーが組み込みの REPLY メニュー項目を使用してタイムライン アイテムに返信しました。

{
  "collection": "timeline",
  "itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "operation": "INSERT",
  "userToken": "harold_penguin",
  "verifyToken": "random_hash_to_verify_referer",
  "userActions": [
    {
      "type": "REPLY"
    }
  ]
}

itemId 属性は、次の項目を含むアイテムの ID に設定されています。

  • inReplyTo 属性で、返信するタイムライン アイテムの ID に設定する。
  • text 属性をテキストの文字起こしに設定しました。
  • recipients 属性(存在する場合)が応答するタイムライン アイテムの creator に設定されている。

例:

{
  "kind": "glass#timelineItem",
  "id": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "inReplyTo": "3236e5b0-b282-4e00-9d7b-6b80e2f47f3d",
  "text": "This is a text reply",
  "recipients": [
    {
      "id": "CREATOR_ID",
      "displayName": "CREATOR_DISPLAY_NAME",
      "imageUrls": [
        "CREATOR_IMAGE_URL"
      ]
    }
  ]
}

削除

ユーザーがタイムライン アイテムを削除しました。

{
  "collection": "timeline",
  "itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "operation": "DELETE",
  "userToken": "harold_penguin",
  "verifyToken": "random_hash_to_verify_referer",
  "userActions": [
    {
      "type": "DELETE"
    }
  ]
}

itemId 属性は、削除されたアイテムの ID に設定されています。アイテムに、ID と isDeleted プロパティ以外のメタデータが含まれなくなりました。

カスタム メニュー項目を選択しました

ユーザーが、サービスによって設定されたカスタム メニュー アイテムを選択しました。

{
  "collection": "timeline",
  "itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "operation": "UPDATE",
  "userToken": "harold_penguin",
  "userActions": [
    {
      "type": "CUSTOM",
      "payload": "PING"
    }
  ]
}

itemId 属性は、ユーザーが選択したメニュー アイテムの ID に設定されます。

userActions 配列には、ユーザーがこのアイテムに対して行ったカスタム アクションのリストが格納されます。これらのサービスは、それに応じて処理する必要があります。

位置情報の更新

現在のユーザーは新しい場所を利用できます。

{
  "collection": "locations",
  "itemId": "latest",
  "operation": "UPDATE",
  "userToken": "harold_penguin",
  "verifyToken": "random_hash_to_verify_referer"
}

Glassware が位置情報の更新を受信したら、glass.locations.get エンドポイントにリクエストを送信して、既知の最新の位置情報を取得します。Glassware は 位置情報の更新を 10 分ごとに受け取ります

音声コマンド

ユーザーが音声コマンドを有効にしました。例: 「OK Glass, メモして(猫のストリーム)、チポトレの誕生日は明日です。」Glassware に次の通知が送信されます。

{
  "collection": "timeline",
  "operation": "INSERT",
  "userToken": "chipotle's_owner",
  "verifyToken": "mew mew mew",
  "itemId": "<ITEM_ID>",
  "userActions": [
    {“type”: "LAUNCH"}
  ]
}

この通知は、userActions プロパティの LAUNCH 値によって他の通知と区別されます。

その後、itemId の値を使用してタイムラインのアイテムを取得できます。

{
  "id": "<ITEM_ID>",
  "text": "Chipotle's birthday is tomorrow",
  "recipients": [
    {"id": "CAT_STREAM"}
  ]
}

recipients プロパティには、使用された音声コマンドを表す連絡先の id が含まれます。