Karty statyczne

Za pomocą prostych interfejsów API REST możesz wstawiać, aktualizować, odczytywać i usuwać karty statyczne. Dodatkowo możesz dołączać obiekty do karty statycznej, na przykład lokalizacji lub multimediów.

Działanie

Karty statyczne znajdują się domyślnie po prawej stronie zegara Glass i zawierają informacje istotne dla użytkownika w momencie dostawy. Nie wymagają one natychmiastowej uwagi, tak jak karty na żywo. Użytkownicy mogą czytać kartę lub korzystać z niej w dogodnym dla siebie czasie.

Gdy Glassware wkłada karty statyczne do osi czasu, urządzenie może odtwarzać dźwięk powiadomienia, aby ostrzec użytkowników. Wszystkie poprzednie karty statyczne również zmieniają się w prawo i znikają z osi czasu po 7 dniach lub po upływie 200 kart.

Kiedy ich używać

Karty statyczne świetnie nadają się do wysyłania użytkownikom powiadomień okresowych. Na przykład usługi związane z dostarczaniem najnowszych wiadomości. Karty statyczne interfejsu API lustrzanych mogą też uruchamiać aktywne karty lub zanurzenie w menu OPEN_URI. Pozwala to tworzyć interakcje hybrydowe, które wykorzystują karty statyczne jako powiadomienia, oraz kartę na żywo lub immersję, aby zwiększyć interaktywność.

Pełną listę możliwych operacji na elementach osi czasu znajdziesz w dokumentacji.

Wkładanie kart statycznych

Aby wstawić karty statyczne (elementy na osi czasu), POST przedstaw element JSON na osi czasu w punkcie końcowym REST.

Większość pól w elemencie osi czasu jest opcjonalna. W najprostszej postaci element na osi czasu zawiera tylko krótki tekst, jak w tym przykładzie:

Nieprzetworzony protokół 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()

Pomyślnie otrzymasz kod odpowiedzi 201 Created z pełną kopią utworzonego elementu. W poprzednim przykładzie pomyślna odpowiedź może wyglądać tak:

Nieprzetworzony protokół 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"
}

Wstawiony element, który pojawi się na osi czasu użytkownika, będzie wyglądać tak:

Wstawianie elementu na osi czasu z załącznikiem

Obraz wart jest tysiąc słów, czyli więcej, niż mieści się na osi czasu. W tym celu możesz też dołączyć obrazy i filmy do elementu na osi czasu. Oto przykład wstawiania elementu osi czasu ze zdjęciem:

Nieprzetworzony protokół 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()

Element na osi czasu z dołączonym obrazem wygląda mniej więcej tak:

Załączanie filmu

Jeśli załączasz pliki wideo do elementów na osi czasu, zalecamy przesłanie ich strumieniowo zamiast przesyłania całego ładunku naraz. Interfejs Google Mirror API obsługuje strumieniowe przesyłanie danych przez HTTP, pobieranie progresywne i protokół RTSP. Protokół RTSP jest często zablokowany przez zapory sieciowe, dlatego używaj w miarę możliwości innych opcji.

Aby odtwarzać strumieniowo film, użyj wbudowanej opcji PLAY_VIDEO i określ adres URL filmu jako payload. Więcej informacji znajdziesz w artykule na temat dodawania wbudowanych pozycji menu i obsługiwanych formatów multimediów.

Z podziałem na strony

Dzielisz na strony elementy na osi, które nie mieszczą się na jednej karcie osi czasu, ale powinny być powiązane z tą samą kartą. Podział elementów na strony dotyczy tego samego elementu timeline.id i zapewnia taki sam zestaw elementów menu. Gdy użytkownik kliknie element podzielony na strony, pojawi się pozycja Więcej informacji.

Google Glass automatycznie dzieli na strony elementy na osi czasu, które wyświetlają text. Aby umożliwić Google Glass automatyczne dzielenie treści na strony html, użyj tagu article z właściwością klasy ustawioną na auto-paginate, jak w tym przykładzie:

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

W podziale na strony użyj tagu article dla treści, które chcesz wyświetlać na poszczególnych kartach. Google Glass wyświetla zawartość każdego tagu article na osobnej karcie osi czasu. Możesz na przykład utworzyć element podziału na strony z użyciem tego kodu 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>

Domyślnie pierwsza strona osi czasu podzielona na strony jest wyświetlana jako karta okładki i ponownie wyświetlana, gdy użytkownik wybierze opcję menu Więcej informacji. Aby zapobiec wyświetlaniu pierwszej karty po kliknięciu Więcej informacji, możesz określić klasę CSS cover-only dla pierwszego tagu <article>:

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

Klasa cover-only obsługuje też automatycznie podzielone na strony elementy osi czasu:

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

Grupowanie

Grupowanie pozwala grupować powiązane, ale różniące się elementy, jak na przykład poszczególne wiadomości w wątku e-maila. Pakiety mają główną kartę okładki, którą użytkownik klika, aby wyświetlić oś czasu zawierającą inne karty w pakiecie. Pakiety różnią się od zwykłych kart na osi czasu od wierzchu w prawym górnym rogu karty okładki pakietu.

Aby połączyć elementy na osi czasu, utwórz je z taką samą wartością w bundleId. Ostatni dodany element to karta okładki pakietu.

Poniższa ilustracja przedstawia kartę tytułową złożoną z rogów w prawym górnym rogu i dwie karty poniżej.

Odczytywanie elementów osi czasu

Twoja usługa ma dostęp do wszystkich utworzonych elementów osi czasu i wszystkich udostępnionych na niej elementów na osi czasu. Dowiedz się, jak wyświetlić listę osi czasu, które są widoczne dla usługi.

Nieprzetworzony protokół 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()

Aby pobrać, zaktualizować i usunąć elementy osi czasu, możesz użyć innych operacji REST.

Dostęp do załączników

Załączniki do elementu na osi czasu możesz wyświetlić, korzystając z właściwości tablicy o nazwie attachments. Dane binarne można pobrać za pomocą właściwości contentUrl załącznika lub punktu końcowego załączników.

Nieprzetworzony protokół 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();

Tworzę pozycje menu

Elementy menu pozwalają użytkownikom wykonywać działania związane z kartą osi czasu. Są 2 rodzaje elementów: wbudowane i niestandardowe menu.

Wbudowane pozycje menu umożliwiają korzystanie ze specjalnych funkcji usługi Glass, takich jak odczytywanie kart na osi czasu, nawigowanie do lokalizacji, udostępnianie obrazu czy odpowiadanie na wiadomości.

Niestandardowe pozycje menu umożliwiają aplikacji wyświetlanie informacji o swoim urządzeniu Glass, a także możesz dodać ikonę elementu menu, która pasuje do Twojej marki.

Dodawanie wbudowanych pozycji menu

Możesz dodać wbudowane elementy menu do osi czasu, wypełniając je menuItems array. Aby użyć wbudowanej pozycji menu, musisz wypełnić tylko właściwość action każdego atrybutu menuItem.

Nieprzetworzony protokół 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"
    }
  ]
}

Definiowanie niestandardowych pozycji menu

Jeśli wbudowane elementy menu nie sprawdzają się w Twoim przypadku, możesz utworzyć własne pozycje menu, wykonując przy tym własne działania, wykonując następujące czynności podczas wstawiania lub aktualizowania elementu na osi czasu:

  • Określ CUSTOM dla menuItem.action.
  • Określ menuItem.id. Gdy użytkownik kliknie pozycję menu niestandardowego, urządzenie Glassware otrzyma powiadomienie z wartością menuItem.id. Pozwala to określić źródło powiadomienia.
  • Określ menuItem.values, aby dodać iconUrl i displayName widoczne w Google Glass. Wskaż biały obraz o rozmiarze 50 x 50, w kolorze „iconUrl” na przezroczystym tle.
  • Określ displayTime. Jeśli nie określisz wartości displayTime, element osi czasu zostanie przeniesiony na początek osi czasu za każdym razem, gdy użytkownik kliknie element menu niestandardowego.

Nieprzetworzony protokół 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"
      }]
    }
  ]
}

Umożliwianie użytkownikom przypinania karty osi czasu

Możesz utworzyć pozycję menu, która umożliwia użytkownikom przypinanie karty osi czasu, która zawsze wyświetla kartę osi czasu po lewej stronie głównej karty zegara. Użytkownicy mogą odpiąć kartę także za pomocą tego samego elementu menu.

Przypinana pozycja menu to wbudowany element menu, wystarczy więc, że podasz TOGGLE_PINNED action dla menuItem.

Nieprzetworzony protokół 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"
    }
  ...
 ]
}

Subskrypcje

Interfejs Mirror API umożliwia subskrypcję powiadomień wysyłanych, gdy użytkownik wykona określone działania dotyczące Elementu osi czasu lub po zaktualizowaniu lokalizacji użytkownika. Gdy subskrybujesz powiadomienie, podajesz adres URL wywołania zwrotnego, który je przetwarza.

Odbieranie powiadomień

Powiadomienie z interfejsu Mirror API jest wysyłane jako żądanie POST do subskrybowanego punktu końcowego zawierającego treść żądania JSON.

Nieprzetworzony protokół 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)

Jeśli nie wystąpił błąd, usługa musi odpowiedzieć na interfejs API za pomocą kodu stanu HTTP 200 OK. Jeśli usługa zwróci kod błędu, interfejs Mirror API może spróbować ponownie wysłać powiadomienie do Twojej usługi.

Typy powiadomień

Interfejs Mirror API wysyła inny ładunek powiadomień dla różnych zdarzeń.

Odpowiedz

Użytkownik odpowiedział na Twoją oś czasu za pomocą wbudowanego elementu menu REPLY:

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

Atrybut itemId jest ustawiony na ID elementu, który zawiera:

  • Atrybut inReplyTo został ustawiony na ID elementu osi czasu, na który odpowiada.
  • Atrybut text został ustawiony na transkrypcję tekstu.
  • Atrybut recipients został ustawiony na wartość creator elementu osi czasu, na który odpowiada (jeśli istnieje).

Przykład

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

Usuń

Użytkownik usunął element osi czasu:

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

Wartość atrybutu itemId jest ustawiona na identyfikator usuniętego elementu. Element nie zawiera już metadanych innych niż identyfikator i właściwość isDeleted.

Wybrano pozycję menu niestandardowego

Użytkownik wybrał element menu niestandardowego ustawiony przez Twoją usługę:

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

Atrybut itemId jest ustawiony na identyfikator elementu menu wybranego przez użytkownika.

Tablica userActions zawiera listę działań niestandardowych wykonanych przez użytkownika na tym elemencie. Usługa powinna odpowiednio obsługiwać te działania.

Aktualizacja lokalizacji

Bieżący użytkownik ma dostęp do nowej lokalizacji:

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

Gdy urządzenie Glassware otrzyma aktualizację lokalizacji, wyślij żądanie do punktu końcowego glass.locations.get, by pobrać najnowszą znaną lokalizację. Urządzenie Glassware otrzymuje aktualizacje lokalizacji co 10 minut.

Polecenie głosowe

Użytkownik aktywował polecenie głosowe, na przykład: „Ok Google, zanotuj, Cat Stream, Urodziny Chipotle'a mają jutro”. Do Glassware wysyłane jest to powiadomienie:

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

To powiadomienie różni się od innych powiadomień wartością LAUNCH we właściwości userActions.

Następnie możesz użyć wartości z pola itemId, aby pobrać element osi czasu:

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

Właściwość recipients zawiera element id kontaktu, który reprezentuje użyte polecenie głosowe.