Thẻ tĩnh

Bạn có thể chèn, cập nhật, đọc và xóa thẻ tĩnh bằng các API REST đơn giản. Ngoài ra, bạn có thể đính kèm các đối tượng vào thẻ tĩnh, chẳng hạn như vị trí hoặc nội dung nghe nhìn.

Cách hoạt động

Theo mặc định, thẻ tĩnh nằm ở bên phải đồng hồ Glass và hiển thị thông tin liên quan đến người dùng tại thời điểm phân phối. Tuy nhiên, các chức năng này không yêu cầu sự chú ý ngay lập tức như thẻ trực tiếp và người dùng có thể chọn đọc hoặc thao tác trên thẻ khi rảnh.

Khi Glassware chèn thẻ tĩnh vào dòng thời gian, Glass có thể phát âm thanh thông báo để cảnh báo cho người dùng. Tất cả thẻ tĩnh trước đó cũng chuyển sang phải và biến mất khỏi dòng thời gian sau 7 ngày hoặc khi 200 thẻ mới hơn.

Thời điểm nên sử dụng thành phần địa điểm của đơn vị liên kết

Thẻ tĩnh rất phù hợp để gửi thông báo định kỳ cho người dùng khi có những việc quan trọng xảy ra. Ví dụ: dịch vụ phân phối tin tức gửi tin bài hàng đầu khi chúng xảy ra. Thẻ tĩnh của Mirror API cũng có thể bắt đầu thẻ trực tiếp hoặc được nhúng thông qua mục trong trình đơn OPEN_URI. Điều này cho phép bạn tạo ra các hoạt động tương tác kết hợp sử dụng thẻ tĩnh làm thông báo và một thẻ trực tiếp hoặc trải nghiệm nhúng để có trải nghiệm tương tác nhiều hơn.

Để biết danh sách đầy đủ các thao tác có thể thực hiện cho các mục tiến trình, hãy xem tài liệu tham khảo.

Chèn thẻ tĩnh

Để chèn thẻ tĩnh (các mục trong dòng thời gian), hãy ĐĂNG bản trình bày JSON của một mục dòng thời gian vào điểm cuối REST.

Hầu hết các trường trong một mục dòng thời gian là không bắt buộc. Ở dạng đơn giản nhất, một mục trên dòng thời gian chỉ chứa một tin nhắn văn bản ngắn, như trong ví dụ sau:

HTTP thô

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()

Khi thành công, bạn sẽ nhận được mã phản hồi 201 Created với bản sao đầy đủ của mục đã tạo. Trong ví dụ trước, phản hồi thành công có thể có dạng như sau:

HTTP thô

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

Mục được chèn sẽ xuất hiện trong dòng thời gian của người dùng có dạng như sau:

Chèn một mục dòng thời gian có tệp đính kèm

Một bức ảnh đáng giá một nghìn từ, đủ để bạn có thể vừa với một mục trong dòng thời gian. Để đạt được mục tiêu này, bạn cũng có thể đính kèm hình ảnh và video vào một mục trên dòng thời gian. Sau đây là ví dụ về cách chèn mục trong dòng thời gian có tệp đính kèm là ảnh:

HTTP thô

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()

Mục dòng thời gian có hình ảnh đính kèm trông giống như sau trên Glass:

Đang đính kèm video

Nếu đang đính kèm tệp video vào các mục trong dòng thời gian, bạn nên phát trực tuyến video thay vì tải toàn bộ trọng tải lên cùng lúc. API Google Mirror hỗ trợ phát trực tuyến bằng tính năng phát trực tiếp HTTP, tải xuống liên tục và giao thức truyền trực tuyến theo thời gian thực (RTSP). RTSP thường bị chặn bởi tường lửa, vì vậy hãy sử dụng các tùy chọn khác khi có thể.

Để phát trực tuyến video, hãy sử dụng mục trong trình đơn tích hợp PLAY_VIDEO và chỉ định URL của video làm payload của mục trong trình đơn. Hãy xem phần Thêm các mục trong trình đơn tích hợp sẵncác định dạng nội dung nghe nhìn được hỗ trợ để biết thêm thông tin.

Phân trang

Bạn có thể phân trang các mục trong dòng thời gian không vừa với một thẻ dòng thời gian, nhưng nên được liên kết với cùng một thẻ. Các mục được phân trang đều có cùng một timeline.id và do đó có cùng một tập hợp các mục trong trình đơn. Khi người dùng nhấn vào một mục trên dòng thời gian được phân trang, mục trong trình đơn Đọc thêm sẽ xuất hiện.

Glass tự động phân trang các mục theo dòng thời gian hiển thị text. Để Glass tự động phân trang html, hãy sử dụng thẻ article có thuộc tính lớp được đặt thành auto-paginate như trong ví dụ sau:

<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>

Để phân trang theo cách thủ công, hãy sử dụng thẻ article cho nội dung mà bạn muốn hiển thị trên mỗi thẻ. Glass hiển thị nội dung của từng thẻ article trong một thẻ tiến trình phụ riêng biệt. Ví dụ: bạn có thể tạo một mục dòng thời gian được phân trang bằng HTML sau:

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

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

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

Theo mặc định, thẻ đầu tiên của mục trong dòng thời gian được phân trang sẽ hiển thị dưới dạng thẻ bìa và hiển thị lại khi người dùng chọn mục trong trình đơn Đọc thêm. Để thẻ đầu tiên không xuất hiện lại sau khi nhấn vào Đọc thêm, bạn có thể chỉ định lớp CSS cover-only cho thẻ <article> đầu tiên:

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

Lớp cover-only cũng hỗ trợ các mục trong dòng thời gian được tự động phân trang:

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

Nhóm

Tính năng nhóm lại cho phép bạn nhóm các mục có liên quan nhưng riêng biệt lại với nhau, chẳng hạn như đối với từng thư riêng lẻ trong một chuỗi email. Gói có một thẻ bìa chính mà người dùng nhấn vào để hiển thị dòng thời gian phụ có chứa các thẻ khác trong gói. Các gói được phân biệt với thẻ dòng thời gian thông thường bằng một nếp gập ở góc trên bên phải thẻ bìa của gói.

Để nhóm các mục trong dòng thời gian, hãy tạo các mục đó có cùng giá trị cho bundleId. Mục được thêm gần đây nhất là thẻ bìa của gói.

Các hình ảnh sau đây hiển thị một thẻ bìa gói có nếp gập góc ở góc trên cùng bên phải và hai thẻ đi kèm bên dưới.

Đọc mục trong dòng thời gian

Dịch vụ của bạn có thể truy cập vào tất cả các mục dòng thời gian mà dịch vụ đó tạo ra và tất cả các mục trong dòng thời gian được chia sẻ với dịch vụ đó. Đây là cách liệt kê các mục trên dòng thời gian hiển thị cho dịch vụ của bạn.

HTTP thô

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()

Bạn có thể sử dụng các thao tác REST khác để nhận, cập nhậtxoá các mục trong dòng thời gian.

Truy cập vào tệp đính kèm

Bạn có thể truy cập các tệp đính kèm vào một mục trên dòng thời gian thông qua một thuộc tính mảng có tên là attachments. Sau đó, bạn có thể lấy dữ liệu nhị phân của tệp đính kèm thông qua thuộc tính contentUrl của tệp đính kèm hoặc bằng điểm cuối của tệp đính kèm.

HTTP thô

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

Tạo các mục trong trình đơn

Các mục trong trình đơn cho phép người dùng yêu cầu các thao tác liên quan đến thẻ tiến trình và có hai loại: mục trong trình đơn tích hợp sẵn và mục trong trình đơn tuỳ chỉnh.

Các mục trong trình đơn tích hợp sẵn sẽ cung cấp quyền sử dụng các chức năng đặc biệt do Glass cung cấp, chẳng hạn như đọc to thẻ dòng thời gian, di chuyển đến một vị trí, chia sẻ hình ảnh hoặc trả lời một tin nhắn:

Các mục trong trình đơn tuỳ chỉnh cho phép ứng dụng của bạn hiển thị hành vi dành riêng cho Glassware, đồng thời bạn cũng có thể cung cấp biểu tượng mục trong trình đơn để phù hợp với thương hiệu của mình.

Thêm các mục trong trình đơn tích hợp sẵn

Bạn có thể thêm các mục trong trình đơn tích hợp sẵn vào mục dòng thời gian bằng cách điền menuItems array khi chèn mục đó. Để sử dụng một mục trong trình đơn tích hợp sẵn, bạn chỉ cần điền action của từng menuItem.

HTTP thô

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"
    }
  ]
}

Xác định các mục trong trình đơn tuỳ chỉnh

Nếu các mục trong trình đơn tích hợp sẵn không phù hợp với bạn, bạn có thể tạo các mục trong trình đơn tuỳ chỉnh bằng các thao tác của riêng mình bằng cách làm như sau khi chèn hoặc cập nhật mục dòng thời gian:

  • Hãy chỉ định CUSTOM cho menuItem.action.
  • Hãy chỉ định một menuItem.id. Khi người dùng nhấn vào mục trong trình đơn tuỳ chỉnh, Glassware của bạn sẽ nhận được thông báo có menuItem.id được điền sẵn. Điều này cho phép bạn xác định nguồn gốc của thông báo.
  • Chỉ định menuItem.values để thêm một iconUrldisplayName xuất hiện trên Glass. Trỏ đến hình ảnh PNG 50 x 50 có màu trắng với nền trong suốt cho iconUrl.
  • Hãy chỉ định một displayTime. Nếu bạn không chỉ định displayTime, mục dòng thời gian sẽ di chuyển đến trước dòng thời gian khi người dùng nhấn vào mục trong trình đơn tuỳ chỉnh.

HTTP thô

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"
      }]
    }
  ]
}

Cho phép người dùng ghim thẻ dòng thời gian của bạn

Bạn có thể tạo một mục trong trình đơn cho phép người dùng ghim thẻ dòng thời gian, thẻ này sẽ hiển thị vĩnh viễn thẻ dòng thời gian ở bên trái thẻ đồng hồ chính. Người dùng cũng có thể bỏ ghim thẻ bằng cách sử dụng cùng một mục trong trình đơn.

Mục trong trình đơn ghim là một mục trong trình đơn tích hợp sẵn, vì vậy, bạn chỉ cần cung cấp TOGGLE_PINNED action cho menuItem.

HTTP thô

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"
    }
  ...
 ]
}

Gói thuê bao

Mirror API cho phép bạn đăng ký các thông báo được gửi khi người dùng thực hiện hành động cụ thể trên Mục dòng thời gian hoặc khi vị trí người dùng đã được cập nhật. Khi đăng ký một thông báo, bạn sẽ cung cấp một URL gọi lại để xử lý thông báo đó.

Nhận thông báo

Một thông báo từ Mirror API được gửi dưới dạng yêu cầu POST đến điểm cuối đã đăng ký chứa nội dung yêu cầu JSON.

HTTP thô

{
  "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)

Dịch vụ của bạn phải phản hồi API bằng mã trạng thái HTTP 200 OK nếu không có lỗi xảy ra. Nếu dịch vụ của bạn phản hồi bằng mã lỗi, API Mirror có thể thử gửi lại thông báo cho dịch vụ của bạn.

Loại thông báo

Mirror API gửi một gói dữ liệu thông báo khác cho các sự kiện khác nhau.

Trả lời

Người dùng đã trả lời mục dòng thời gian của bạn bằng cách sử dụng mục trong trình đơn REPLY tích hợp:

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

Thuộc tính itemId được đặt thành ID của mục có chứa:

  • Thuộc tính inReplyTo được đặt thành ID của mục trong dòng thời gian mà mục đó trả lời.
  • Thuộc tính text được đặt thành bản chép lời.
  • Thuộc tính recipients được đặt thành creator của mục trong dòng thời gian mà mục đó trả lời, nếu có.

Ví dụ:

{
  "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"
      ]
    }
  ]
}

Xoá

Người dùng đã xoá một mục trong dòng thời gian:

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

Thuộc tính itemId được đặt thành mã nhận dạng của mục đã xoá. Mục này không còn chứa siêu dữ liệu ngoài mã nhận dạng và thuộc tính isDeleted.

Đã chọn mục tuỳ chỉnh trên trình đơn

Người dùng đã chọn một mục trình đơn tuỳ chỉnh do dịch vụ của bạn đặt:

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

Thuộc tính itemId được đặt thành mã nhận dạng của mục trong trình đơn mà người dùng đã chọn.

Mảng userActions chứa danh sách các hành động tuỳ chỉnh mà người dùng đã thực hiện trên mục này. Dịch vụ của bạn sẽ xử lý những thao tác đó cho phù hợp.

Thông tin cập nhật về vị trí

Người dùng hiện tại có thể truy cập vào một vị trí mới:

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

Khi Glassware của bạn nhận được thông tin cập nhật về vị trí, hãy gửi yêu cầu đến điểm cuối glass.locations.get để truy xuất vị trí đã biết mới nhất. Glassware của bạn sẽ nhận được thông tin cập nhật vị trí mười phút một lần.

Lệnh thoại

Người dùng đã kích hoạt một lệnh thoại, ví dụ: "Ok Glass, hãy ghi chú, Cat Stream, sinh nhật của Chipotle là ngày mai". Thông báo sau sẽ được gửi tới Glassware của bạn:

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

Thông báo này được phân biệt với các thông báo khác bằng giá trị LAUNCH trong thuộc tính userActions.

Sau đó, bạn có thể dùng giá trị trong itemId để tìm nạp mục dòng thời gian:

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

Thuộc tính recipients chứa id của địa chỉ liên hệ đại diện cho lệnh thoại được sử dụng.