Karty statyczne

Możesz wstawiać, aktualizować, odczytywać i usuwać karty statyczne za pomocą prostych interfejsów API REST. Możesz też dołączyć do statycznej karty obiekty, takie jak lokalizacja czy multimedia.

Jak działają

Karty statyczne domyślnie znajdują się po prawej stronie zegara Glass i wyświetlają informacje istotne dla użytkownika w momencie dostarczenia. Nie wymagają one jednak natychmiastowej uwagi, jak karty na żywo, a użytkownicy mogą przeczytać informacje na karcie lub podjąć działania w dogodnym dla siebie czasie.

Gdy aplikacja Glassware wstawia statyczne karty na osi czasu, urządzenie Glass może odtwarzać dźwięk powiadomienia, aby ostrzegać użytkowników. Wszystkie poprzednie karty statyczne przesuwają się w prawo i znikają z osi czasu po 7 dniach lub gdy pojawi się 200 nowszych kart.

Kiedy ich używać

Karty statyczne świetnie nadają się do wysyłania okresowych powiadomień do użytkowników, gdy dzieją się ważne rzeczy. Na przykład usługa dostarczania wiadomości, która wysyła najważniejsze informacje na bieżąco. Statyczne karty interfejsu Mirror API mogą też uruchamiać karty na żywo lub immersje za pomocą elementu menu OPEN_URI. Dzięki temu możesz tworzyć interakcje hybrydowe, które wykorzystują karty statyczne jako powiadomienia oraz karty na żywo lub immersyjne, aby zapewnić bardziej interaktywne wrażenia.

Pełną listę możliwych operacji dotyczących elementów osi czasu znajdziesz w dokumentacji.

Wstawianie kart statycznych

Aby wstawić statyczne karty (elementy osi czasu), wyślij POST reprezentację JSON elementu osi czasu do punktu końcowego REST.

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

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

Jeśli operacja się uda, otrzymasz kod odpowiedzi 201 Created z pełną kopią utworzonego elementu. W przypadku poprzedniego przykładu odpowiedź informująca o powodzeniu może wyglądać tak:

Surowy 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, wygląda tak:

Wstawianie elementu osi czasu z załącznikiem

Obraz wart jest tysiąc słów, czyli znacznie więcej niż można zmieścić w elemencie osi czasu. W tym celu możesz też dołączyć obrazy i filmy do elementu osi czasu. Oto przykład wstawiania elementu osi czasu z załącznikiem w postaci zdjęcia:

Surowy 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 osi czasu z załączonym obrazem wygląda na Glass mniej więcej tak:

Dołączanie filmu

Jeśli do elementów osi czasu dołączasz pliki wideo, zalecamy przesyłanie strumieniowe filmu zamiast przesyłania całego pakietu danych naraz. Interfejs Google Mirror API obsługuje strumieniowanie za pomocą transmisji na żywo przez HTTP, pobierania progresywnego i protokołu transmisji strumieniowej w czasie rzeczywistym (RTSP). Protokół RTSP jest często blokowany przez zapory sieciowe, więc w miarę możliwości korzystaj z innych opcji.

Aby przesyłać strumieniowo wideo, użyj wbudowanego elementu menu PLAY_VIDEO i określ adres URL filmu jako payload elementu menu. Więcej informacji znajdziesz w artykułach Dodawanie wbudowanych elementów menuobsługiwane formaty multimediów.

Podział na strony

Możesz podzielić na strony elementy osi czasu, które nie mieszczą się na jednej karcie osi czasu, ale powinny być z nią powiązane. Elementy podzielone na strony mają ten sam timeline.id, a co za tym idzie, ten sam zestaw pozycji menu. Gdy użytkownik kliknie element osi czasu z podziałem na strony, pojawi się element menu Więcej.

Glass automatycznie dzieli na strony elementy osi czasu, które wyświetlają text. Aby Glass automatycznie dzielił na strony element 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>

Aby ręcznie podzielić treść na strony, użyj tagu article w przypadku treści, które chcesz wyświetlać na poszczególnych kartach. Glass wyświetla zawartość każdego tagu article na osobnej karcie podrzędnej osi czasu. Możesz na przykład utworzyć element osi czasu z podziałem na strony, używając 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 karta elementu osi czasu podzielonego na strony jest wyświetlana jako karta okładki i ponownie, gdy użytkownik wybierze pozycję menu Więcej. Aby zapobiec ponownemu wyświetlaniu się pierwszej karty po kliknięciu Więcej, możesz określić klasę CSS dla pierwszego tagu cover-only:<article>

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

Klasa cover-only obsługuje też elementy osi czasu z automatycznym podziałem na strony:

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

Grupowanie

Grupowanie umożliwia łączenie powiązanych, ale odrębnych elementów, np. poszczególnych wiadomości w wątku e-maila. Pakiety mają główną kartę okładki, którą użytkownik klika, aby wyświetlić podosię czasu zawierającą pozostałe karty w pakiecie. Pakiety różnią się od zwykłych kart na osi czasu zagięciem w prawym górnym rogu karty okładki pakietu.

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

Na obrazach poniżej widać kartę okładki pakietu ze zagiętym rogiem w prawym górnym rogu oraz 2 karty pakietu poniżej.

Odczytywanie elementów osi czasu

Usługa może uzyskać dostęp do wszystkich utworzonych przez siebie elementów osi czasu oraz do wszystkich elementów osi czasu, które zostały jej udostępnione. Oto jak wyświetlić elementy osi czasu, które są widoczne dla Twojej usługi.

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

Do pobierania, aktualizowaniausuwania elementów osi czasu możesz używać innych operacji REST.

Uzyskiwanie dostępu do załączników

Dostęp do załączników elementu osi czasu możesz uzyskać za pomocą właściwości tablicy o nazwie attachments. Dane binarne załącznika możesz uzyskać za pomocą właściwości contentUrl załącznika lub punktu końcowego załączników.

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

Tworzenie pozycji menu

Pozycje menu umożliwiają użytkownikom żądanie działań związanych z kartą osi czasu i występują w 2 rodzajach: wbudowane pozycje menu i niestandardowe pozycje menu.

Wbudowane pozycje menu zapewniają dostęp do specjalnych funkcji Glass, takich jak odczytywanie na głos karty osi czasu, nawigowanie do lokalizacji, udostępnianie obrazu czy odpowiadanie na wiadomość:

Niestandardowe elementy menu umożliwiają aplikacji udostępnianie funkcji specyficznych dla Glassware. Możesz też dodać ikonę elementu menu, która będzie pasować do Twojej marki.

Dodawanie wbudowanych pozycji menu

Wbudowane elementy menu możesz dodawać do elementów osi czasu, wypełniając pole menuItems array podczas ich wstawiania. Aby użyć wbudowanego elementu menu, wystarczy wypełnić pole action każdego elementu menuItem.

Surowy 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 działają, możesz utworzyć niestandardowe elementy menu z własnymi działaniami. W tym celu podczas wstawiania lub aktualizowania elementu osi czasu wykonaj te czynności:

  • Wpisz CUSTOM w polu menuItem.action.
  • Określ wartość menuItem.id. Gdy użytkownicy klikną niestandardowy element menu, aplikacja Glassware otrzyma powiadomienie z wypełnionym polem menuItem.id. Dzięki temu możesz określić źródło powiadomienia.
  • Określ menuItem.values, aby dodać iconUrldisplayName, które pojawią się na Glass. Wskaż obraz PNG o wymiarach 50 x 50 pikseli, który jest biały i ma przezroczyste tło, w przypadku iconUrl.
  • Określ wartość displayTime. Jeśli nie określisz wartości displayTime, element osi czasu będzie przenoszony na początek osi za każdym razem, gdy użytkownicy klikną niestandardowy element menu.

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

Zezwalanie użytkownikom na przypinanie karty osi czasu

Możesz utworzyć element menu, który umożliwi użytkownikom przypinanie karty osi czasu, dzięki czemu będzie ona stale wyświetlana po lewej stronie głównej karty zegara. Użytkownicy mogą też odpiąć kartę, korzystając z tego samego elementu menu.

Element menu przypinania jest wbudowanym elementem menu, więc wystarczy podać TOGGLE_PINNED action dla menuItem.

Surowy 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 subskrybowanie powiadomień wysyłanych, gdy użytkownik wykonuje określone działania na karcie osi czasu lub gdy jego lokalizacja zostanie zaktualizowana. Gdy subskrybujesz powiadomienie, podajesz adres URL wywołania zwrotnego, który przetwarza powiadomienie.

Otrzymywanie powiadomień

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

Surowy 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ł żaden błąd, usługa musi odpowiedzieć na interfejs API kodem stanu HTTP 200 OK. Jeśli Twoja usługa odpowie kodem błędu, Mirror API może spróbować ponownie wysłać powiadomienie do Twojej usługi.

Typy powiadomień

Interfejs Mirror API wysyła różne ładunki powiadomień w zależności od zdarzenia.

Odpowiedz

Użytkownik odpowiedział na element osi czasu, korzystając z 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 produktu zawierającego:

  • inReplyTo ustawiony na ID elementu osi czasu, na który odpowiada.
  • text ustawiony na transkrypcję tekstu.
  • recipients ustawiony na creator elementu osi czasu, na który odpowiada, jeśli taki element 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"
    }
  ]
}

Atrybut itemId jest ustawiony na identyfikator usuniętego produktu. Element nie zawiera już metadanych innych niż identyfikator i właściwość isDeleted.

Wybrano niestandardową pozycję menu

Użytkownik wybrał niestandardowy element menu 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, który wybrał użytkownik.

Tablica userActions zawiera listę działań niestandardowych, które użytkownik wykonał w przypadku tego elementu. Usługa powinna odpowiednio obsługiwać te działania.

Aktualizacja lokalizacji

Dla obecnego użytkownika jest dostępna nowa lokalizacja:

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

Gdy Glassware otrzyma informację o zmianie lokalizacji, wyślij żądanie do punktu końcowego glass.locations.get, aby pobrać ostatnią znaną lokalizację. Glassware otrzymuje aktualizacje lokalizacji co 10 minut.

Polecenia głosowe

Użytkownik aktywował polecenie głosowe, na przykład: „OK Glass, zrób notatkę, Cat Stream, urodziny Chipotle są jutro”. Na Twoje urządzenie Glassware zostanie wysłane 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 w itemId, aby pobrać element osi czasu:

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

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