靜態卡片

您可以使用簡單的 REST API 插入、更新、讀取及刪除靜態卡片。此外,您也可以將物件附加至靜態卡片,如位置或媒體。

運作方式

根據預設,靜態資訊卡位於 Glass 時鐘的右側,並在傳送時顯示使用者相關資訊。不過,使用者不需立即註意,像是即時資訊卡等。使用者也能自由選擇是否閱讀或執行這些動作。

Glassware 將靜態資訊卡插入時間軸時,Google 可能會播放通知音效來提醒使用者。先前所有的靜態資訊卡也會向右移動,並在 7 天或較新的 200 張資訊卡時從時間軸消失。

使用時機

每當發生重要事件,靜態資訊卡就能向使用者提供定期通知。舉例來說,新聞服務會在發生時傳送焦點新聞。鏡像 API 靜態資訊卡也可以透過 OPEN_URI 選單項目來啟動即時資訊卡沉浸式。如此一來,您就能建立使用靜態資訊卡做為通知的即時互動,以及即時資訊卡或沉浸式體驗,以提供更具互動性的體驗。

如需時間軸項目的完整清單,請參閱參考說明文件

插入靜態卡片

如要「插入」靜態資訊卡 (時間軸項目),請將 時間軸項目的 JSON 表示法 張貼至 REST 端點。

時間軸項目中的大多數欄位都是選填的。簡單來說,時間軸項目只包含簡短簡訊,如以下範例所示:

原始 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"
}

插入項目會顯示在使用者時間軸中,如下所示:

插入含有附件的時間軸項目

一張相片勝過千言萬語,遠超過單個時程。為此,您也可以將圖片和影片附加到時間軸項目。以下範例說明如何插入含有相片附件的時間軸項目:

原始 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 選單項目,並將影片網址指定為選單項目的 payload。詳情請參閱新增內建選單項目支援的媒體格式

分頁

您可以分頁無法呈現在單一時間軸資訊卡上,但應該與同一張資訊卡建立關聯的時間軸項目。分頁後的項目共用相同的 timeline.id,因此相同的選單項目集。使用者輕觸分頁的時間軸項目時,畫面上會顯示「Read more」(顯示更多) 選單項目。

Glass 會自動為顯示 text 的時間軸項目進行分頁。如要讓 Glass 自動分頁 html,請使用 article 標記,並將類別屬性設為 auto-paginate,如以下範例所示:

<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 值建立時間軸項目。最近新增的項目是套裝組合的封面卡

下圖顯示一包的封面封面,其右上角有折疊邊,下方有一張組合資訊卡。

讀取時間軸項目

您的服務可以存取其建立的所有時間軸項目,以及共用的所有時間軸項目。以下說明如何列出您的服務可見的時間軸項目。

原始 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();

建立菜單項目

選單項目可讓使用者要求與時間軸資訊卡相關的動作,且有兩種類型:內建選單項目和自訂選單項目。

內建選單項目可存取微資料提供的特殊功能,例如大聲讀出時間軸資訊卡、導航至指定位置、分享圖片或回覆訊息:

自訂選單項目可讓您的應用程式顯示 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。當使用者輕觸自訂選單項目時,您的 Glassware 會收到已填入 menuItem.id 的通知。這可讓您決定通知的來源。
  • 指定 menuItem.values 以新增顯示在 Glass 上的 iconUrldisplayName。指向白色的 50 x 50 PNG 圖片,並使用 iconUrl 為背景透明。
  • 指定 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"
      }]
    }
  ]
}

允許使用者固定時間軸資訊卡

您可以建立選單項目,讓使用者將圖釘資訊卡固定在主要時鐘資訊卡的左側。使用者也可以使用相同的選單項目來取消固定資訊卡。

固定選單項目是內建選單項目,因此您只需為 menuItem 提供 TOGGLE_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 訂閱 當使用者對時間軸項目執行特定動作,或使用者位置更新時傳送的通知。訂閱通知時,您必須提供可處理通知的回呼網址。

接收通知

鏡射 API 的通知將以 POST 要求的形式傳送至包含 JSON 要求主體的訂閱端點。

原始 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)

如果服務發生錯誤,您的服務必須使用 200 OK HTTP 狀態碼回應 API。 如果您的服務以錯誤代碼回應,則 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, 注意, Cat Stream, Chipotle 的生日是明天」。以下通知會傳送到您的 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 聯絡人。