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 menu i obsł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, aktualizowania i usuwania 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
CUSTOMw polumenuItem.action. - Określ wartość
menuItem.id. Gdy użytkownicy klikną niestandardowy element menu, aplikacja Glassware otrzyma powiadomienie z wypełnionym polemmenuItem.id. Dzięki temu możesz określić źródło powiadomienia. - Określ
menuItem.values, aby dodaćiconUrlidisplayName, 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 przypadkuiconUrl. Określ wartość
displayTime. Jeśli nie określisz wartościdisplayTime, 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:
inReplyToustawiony naIDelementu osi czasu, na który odpowiada.textustawiony na transkrypcję tekstu.recipientsustawiony nacreatorelementu 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.