Za pomocą prostych interfejsów REST API możesz wstawiać, aktualizować, czytać i usuwać karty statyczne. Możesz też dołączyć do karty statycznej obiekty, takie jak lokalizacja lub materiały multimedialne.
Jak działają
Karty statyczne znajdują się domyślnie po prawej stronie zegara w Glass i wyświetlają informacje istotne dla użytkownika w momencie dostawy. Nie wymagają jednak natychmiastowej uwagi, jak karty na żywo, a użytkownicy mogą czytać je lub podejmować działania na ich podstawie we własnym tempie.
Gdy Glassware wstawia statyczne karty na osi czasu, Glass może odtworzyć dźwięk powiadomienia, aby ostrzec użytkowników. Wszystkie wcześniejsze karty statyczne przesuwają się też w prawo i znikają z osi czasu po 7 dniach lub gdy pojawi się 200 nowszych kart.
Kiedy ich używać
Karty statyczne są świetnym sposobem na wysyłanie okresowych powiadomień do użytkowników, gdy dzieją się ważne rzeczy.
Przykładem może być usługa dostarczania wiadomości, która wysyła najważniejsze wiadomości w miarę ich pojawiania się. Statyczne karty interfejsu Mirror API mogą też uruchamiać karty na żywo lub immersję za pomocą pozycji menu OPEN_URI
. Dzięki temu możesz tworzyć interakcje hybrydowe, które wykorzystują karty statyczne jako powiadomienia i 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ć karty statyczne (elementy osi czasu), prześlij reprezentację elementu osi czasu w formacie JSON do punktu końcowego REST.
Większość pól w elemencie osi czasu jest opcjonalna. W najprostszej formie element osi czasu zawiera tylko krótką wiadomość tekstową, jak w tym przykładzie:
Nieprzetworzony 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()
W przypadku powodzenia otrzymasz kod odpowiedzi 201 Created
z pełną kopią utworzonego elementu. W przypadku poprzedniego przykładu odpowiedź informująca o pomyślnym zakończeniu może wyglądać tak:
Nieprzetworzony 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"
}
Wstawioną pozycję, która pojawi się na osi czasu użytkownika, będzie można zobaczyć w takiej postaci:
Wstawianie elementu osi czasu z załącznikiem
Jedno zdjęcie wyraża więcej niż tysiąc słów, czyli dużo więcej niż możesz 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łączonym zdjęciem:
Nieprzetworzony 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 w Google Glass tak:
Dołączanie filmu
Jeśli załączasz pliki wideo do elementów osi czasu, zalecamy przesyłanie ich strumieniowo zamiast przesyłać cały ładunek naraz. Interfejs Google Mirror API obsługuje strumieniowanie z wykorzystaniem transmisji na żywo przez HTTP, pobierania progresywnego i protokołu strumieniowego przesyłania w czasie rzeczywistym (RTSP). Protokół RTSP jest często blokowany przez zapory sieciowe, dlatego w miarę możliwości używaj innych opcji.
Aby przesyłać strumieniowo filmy, użyj wbudowanego elementu menu PLAY_VIDEO
i podaj adres URL filmu jako payload
elementu menu. Więcej informacji znajdziesz w artykule Dodawanie wbudowanych elementów menu oraz 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ć powiązane z tą samą kartą. Wszystkie elementy pogrupowane w sekcji mają ten sam timeline.id
, a co za tym idzie, ten sam zestaw elementów menu. Gdy użytkownik kliknie element strony przewijanej, pojawi się menu z opcją Więcej informacji.
Glass automatycznie dzieli na strony elementy osi czasu, które wyświetlają się na text
. Aby Glass automatycznie dzielił stronę html
, użyj tagu article
z właściwością class 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 utworzyć strony, użyj tagu article
w przypadku treści, które mają być wyświetlane na każdej karcie. Glass wyświetla zawartość każdego tagu article
na osobnej karcie podrzędnej. Możesz na przykład utworzyć podzielony na strony element osi czasu za pomocą 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 na stronicowanej osi czasu jest wyświetlana jako karta tytułowa i ponownie, gdy użytkownik kliknie pozycję menu Więcej informacji. Aby pierwsza karta nie pojawiała się ponownie 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ż automatyczne paginację elementów osi czasu:
<article class="auto-paginate cover-only">
...
Pakiety
Dzięki grupowaniu możesz łączyć powiązane, ale odrębne elementy, np. poszczególne wiadomości w wątku e-mail. Pakiety mają główną kartę okładki, którą użytkownik może kliknąć, aby wyświetlić podczas trwania podczas, zawierający inne karty w pakiecie. Pakiety różnią się od zwykłych kart osi czasu zagięciem w prawym górnym rogu karty z okładką.
Aby połączyć elementy osi czasu, utwórz je z tą samą wartością atrybutu bundleId
. Ostatnio dodany element to karta okładki pakietu.
Na poniższych obrazach widać kartę z pakietem z zawiniętym rogiem w prawym górnym rogu oraz 2 karty z pakietu poniżej.
Czytanie elementów osi czasu
Usługa ma dostęp do wszystkich elementów osi czasu, które utworzyła, oraz 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.
Nieprzetworzony 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()
Możesz używać innych operacji REST, aby pobierać, aktualizować i usuwać elementy osi czasu.
Dostęp do załączników
Do załączników dołączonych do elementu osi czasu możesz uzyskać dostęp za pomocą właściwości tablicy o nazwie attachments
.
Następnie możesz uzyskać dane binarne załącznika za pomocą właściwości contentUrl
załącznika lub za pomocą punktu końcowego attachments.
Nieprzetworzony 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 wykonywanie działań związanych z kartą osi czasu. Występują one w 2 typach: wbudowane pozycje menu i niestandardowe pozycje menu.
Wbudowane pozycje menu zapewniają dostęp do specjalnych funkcji Google Glass, takich jak odczytywanie na głos karty osi czasu, nawigowanie do lokalizacji, udostępnianie zdjęcia czy odpowiadanie na wiadomość:
Niestandardowe elementy menu umożliwiają aplikacji wyświetlanie zachowań związanych z Twoim Glassware. Możesz też podać ikonę elementu menu pasującą do Twojej marki.
Dodawanie wbudowanych elementów menu
Możesz dodawać do elementów osi czasu wbudowane elementy menu, wypełniając podczas wstawiania te pola:
menuItems array
.
Aby użyć wbudowanego elementu menu, musisz wypełnić tylko pole
action
w każdym menuItem
.
Nieprzetworzony 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 Ci nie odpowiadają, możesz utworzyć własne elementy menu, wykonując te czynności podczas wstawiania lub aktualizowania elementu na osi czasu:
- W polu
menuItem.action
wpiszCUSTOM
. - Podaj wartość w polu
menuItem.id
. Gdy użytkownicy klikną niestandardowy element menu, Twoja aplikacja Glassware otrzyma powiadomienie z wypełnionym parametremmenuItem.id
. Dzięki temu możesz określić źródło powiadomienia. - Określ
menuItem.values
, aby dodaćiconUrl
idisplayName
, które będą widoczne na Glass. Wskaż obraz PNG o wymiarach 50 x 50, który jest biały i ma przezroczyste tło. Taki obraz będzie miał wartośćiconUrl
. Podaj wartość w polu
displayTime
. Jeśli nie określisz wartościdisplayTime
, element osi czasu przesunie się na początek osi, gdy użytkownicy klikną niestandardowy element menu.
Nieprzetworzony 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żliwia użytkownikom przypinanie karty osi czasu. Karta osi czasu będzie się wtedy wyświetlać na stałe po lewej stronie głównej karty zegara. Użytkownicy mogą też odpiąć kartę, korzystając z tego samego menu.
Element menu przypinania jest wbudowanym elementem menu, więc wystarczy, że podasz parametr TOGGLE_PINNED
action
dla parametru menuItem
.
Nieprzetworzony 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ń, które są wysyłane, gdy użytkownik wykona określone działania dotyczące elementu osi czasu lub gdy zaktualizuje swoją lokalizację. 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 z zawartością żądania JSON
.
Nieprzetworzony 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ć interfejsowi API kodem stanu HTTP 200 OK
.
Jeśli usługa odpowie kodem błędu, interfejs Mirror API może spróbować ponownie wysłać powiadomienie do usługi.
Typy powiadomień
Interfejs Mirror API wysyła różne dane powiadomienia w zależności od zdarzenia.
Odpowiedz
Użytkownik odpowiedział na Twój 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
elementu zawierającego:
- atrybut
inReplyTo
ustawiony naID
elementu osi czasu, na który jest odpowiedzią; - atrybut
text
ustawiony na transkrypcję tekstu. - Atrybut
recipients
ustawiony nacreator
elementu osi czasu, do którego jest on odpowiedzią (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"
}
]
}
Atrybut itemId
jest ustawiony na identyfikator usuniętego elementu. Element nie zawiera już żadnych metadanych poza identyfikatorem i właściwością isDeleted
.
Wybrano element 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 wybranego przez użytkownika elementu menu.
Tablica userActions
zawiera listę działań niestandardowych, które użytkownik wykonał na tym elemencie. Usługa powinna odpowiednio obsługiwać te działania.
Aktualizacja lokalizacji
Nowa lokalizacja jest dostępna dla bieżącego użytkownika:
{
"collection": "locations",
"itemId": "latest",
"operation": "UPDATE",
"userToken": "harold_penguin",
"verifyToken": "random_hash_to_verify_referer"
}
Gdy Glassware otrzyma aktualizację lokalizacji, wyślij żądanie do punktu końcowego glass.locations.get, aby 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 Glass, zanotuj, że jutro jest urodziny Cat Stream w Chipotle”. Na Twój adres Glassware:
{
"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
w 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żytą komendę głosową.