Schede statiche

Puoi inserire, aggiornare, leggere ed eliminare carte statiche utilizzando semplici API REST. Inoltre, puoi collegare oggetti a una scheda statica, come una posizione o contenuti multimediali.

Funzionamento

Per impostazione predefinita, le schede statiche si trovano a destra dell'orologio di Glass e mostrano le informazioni pertinenti per l'utente al momento della consegna. Tuttavia, non richiedono un intervento immediato come i live card e gli utenti possono scegliere di leggere o interagire con le schede a loro piacimento.

Quando Glassware inserisce schede statiche nella sequenza temporale, Glass potrebbe riprodurre un suono di notifica per avvisare gli utenti. Anche tutte le schede statiche precedenti si spostano verso destra e scompaiono dalla sequenza temporale dopo 7 giorni o quando ne sono più recenti 200.

Quando utilizzarli

Le schede statiche sono ideali per inviare notifiche periodiche agli utenti quando si verificano eventi importanti. ad esempio un servizio di consegna di notizie che invia le notizie principali non appena si presentano. Le schede statiche dell'API Mirror possono anche avviare schede live o immersioni tramite la voce di menu OPEN_URI. Ciò ti consente di creare interazioni ibride che utilizzano schede statiche come notifiche e una scheda dal vivo o un'esperienza immersiva per un'esperienza più interattiva.

Per un elenco completo delle possibili operazioni per gli elementi della sequenza temporale, consulta la documentazione di riferimento.

Inserimento di schede statiche

Per inserire schede statiche (elementi della cronologia), POSTA una rappresentazione JSON di un elemento della sequenza temporale sull'endpoint REST.

La maggior parte dei campi di un elemento della sequenza temporale è facoltativa. Nella sua forma più semplice, un elemento della sequenza temporale contiene solo un breve messaggio di testo, come in questo esempio:

HTTP non elaborato

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

Se l'operazione riesce, riceverai un codice di risposta 201 Created con una copia completa dell'elemento creato. Nell'esempio precedente, una risposta corretta potrebbe avere il seguente aspetto:

HTTP non elaborato

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

L'elemento inserito che verrebbe visualizzato nella sequenza temporale dell'utente ha il seguente aspetto:

Inserimento di un elemento della sequenza temporale con un allegato

Un'immagine vale più di mille parole, molte di più di quanto possano rientrare in un elemento della cronologia. Puoi anche allegare immagini e video a un elemento della sequenza temporale. Ecco un esempio di come inserire un elemento della sequenza temporale con una foto allegata:

HTTP non elaborato

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

Un elemento della sequenza temporale con un'immagine allegata ha il seguente aspetto su Glass:

Caricamento allegato del video in corso...

Se alleghi i file video agli elementi della sequenza temporale, ti consigliamo di trasmettere il video in streaming anziché caricare l'intero payload. L'API Google Mirror supporta lo streaming con live streaming HTTP, il download progressivo e il protocollo di streaming in tempo reale (RTSP). RTSP è spesso bloccato dai firewall, quindi utilizza le altre opzioni quando possibile.

Per riprodurre il video in streaming, utilizza la voce di menu integrata PLAY_VIDEO e specifica l'URL del video come payload della voce di menu. Per ulteriori informazioni, consulta la sezione Aggiungere voci di menu integrate e i formati multimediali supportati.

Impaginazione

Puoi impaginare gli elementi della sequenza temporale che non rientrano in una singola scheda della sequenza temporale, ma che dovrebbero essere associati alla stessa scheda. Gli elementi impaginati condividono tutti lo stesso timeline.id e, pertanto, hanno lo stesso insieme di voci di menu. Quando un utente tocca un elemento della sequenza temporale impaginato, viene visualizzata la voce di menu Scopri di più.

Glass esegue automaticamente l'impaginazione degli elementi della sequenza temporale che mostrano text. Per fare in modo che Glass esegua automaticamente la suddivisione in pagine di html, utilizza il tag article con la proprietà della classe impostata su auto-paginate come nell'esempio seguente:

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

Per impaginare manualmente, utilizza il tag article per i contenuti che vuoi visualizzare su ogni scheda. Glass mostra i contenuti di ogni tag article in una scheda separata della cronologia secondaria. Ad esempio, puoi creare un elemento di sequenza temporale suddiviso in pagine con il seguente codice 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>

Per impostazione predefinita, la prima scheda dell'elemento della sequenza temporale impaginato viene visualizzata come scheda di copertina e viene nuovamente visualizzata quando l'utente seleziona la voce di menu Scopri di più. Per evitare che la prima scheda venga visualizzata di nuovo dopo aver toccato Scopri di più, puoi specificare la classe CSS cover-only per il primo tag <article>:

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

La classe cover-only supporta anche gli elementi della sequenza temporale suddivisi automaticamente in pagine:

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

Raggruppamento

Il raggruppamento ti consente di raggruppare elementi correlati ma distinti, come per i singoli messaggi in un thread di email. I pacchetti hanno una scheda di copertina principale che un utente tocca per visualizzare una cronologia secondaria contenente le altre schede del bundle. I pacchetti si distinguono dalle normali schede della sequenza temporale per la piegatura in un angolo nell'angolo in alto a destra della scheda di copertina del bundle.

Per raggruppare gli elementi della sequenza temporale, creali con lo stesso valore per bundleId. L'elemento aggiunto più di recente è la scheda di copertina del cofanetto.

Le seguenti immagini mostrano una scheda di copertina di un bundle con la piega d'angolo nell'angolo in alto a destra e due schede raggruppate sotto.

Lettura degli elementi della sequenza temporale in corso...

Il tuo servizio può accedere a tutti gli elementi della sequenza temporale che ha creato, nonché a tutti gli elementi della sequenza temporale che sono stati condivisi con il servizio. Ecco come elencare gli elementi della sequenza temporale visibili al tuo servizio.

HTTP non elaborato

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

Puoi utilizzare altre operazioni REST per ottenere, aggiornare ed eliminare gli elementi della sequenza temporale.

Accesso agli allegati

Puoi accedere agli allegati a un elemento della sequenza temporale tramite una proprietà array denominata attachments. Potrai quindi ottenere i dati binari di un collegamento tramite la proprietà contentUrl dell'allegato o tramite l'endpoint degli allegati.

HTTP non elaborato

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

Creazione di voci di menu

Le voci di menu consentono agli utenti di richiedere azioni relative alla scheda della cronologia e sono disponibili in due tipi: voci di menu integrati e voci di menu personalizzate.

Le voci di menu integrate forniscono l'accesso a funzionalità speciali fornite da Glass, come la lettura ad alta voce di una scheda di una sequenza temporale, la navigazione verso una posizione, la condivisione di un'immagine o la risposta a un messaggio:

Le voci di menu personalizzate consentono alla tua applicazione di esporre il comportamento specifico dei tuoi Glassware e puoi anche fornire un'icona di voce di menu da abbinare al tuo branding.

Aggiunta di voci di menu integrate

Per aggiungere elementi di menu integrati agli elementi della sequenza temporale, compila il menuItems array quando li inserisci. Per usare una voce di menu integrata, devi solo compilare il campo action di ogni menuItem.

HTTP non elaborato

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

Definizione di voci di menu personalizzate

Se le voci di menu integrate non funzionano, puoi creare voci di menu personalizzate con le tue azioni procedendo nel seguente modo quando inserisci o aggiorni una voce della sequenza temporale:

  • Specifica CUSTOM per menuItem.action.
  • Specifica un valore menuItem.id. Quando gli utenti toccano la voce di menu personalizzata, Glassware riceve una notifica con menuItem.id compilato. Ciò consente di determinare l'origine della notifica.
  • Specifica menuItem.values per aggiungere iconUrl e displayName visualizzati su Glass. Posiziona il puntatore del mouse su un'immagine PNG 50 x 50 di colore bianco con uno sfondo trasparente per iconUrl.
  • Specifica un valore displayTime. Se non specifichi un valore displayTime, l'elemento della sequenza temporale viene spostato in primo piano nella sequenza temporale ogni volta che gli utenti toccano la voce di menu personalizzata.

HTTP non elaborato

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

Consentire agli utenti di fissare la scheda della cronologia

Puoi creare una voce di menu che consente agli utenti di fissare la scheda della cronologia, che mostra in modo permanente la scheda della cronologia a sinistra della scheda dell'orologio principale. Gli utenti possono anche sbloccare la scheda utilizzando la stessa voce di menu.

La voce di menu di blocco è una voce di menu integrata, quindi non devi fare altro che fornire TOGGLE_PINNED action per menuItem.

HTTP non elaborato

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

Iscrizioni

L'API Mirror ti consente di abbonarti alle notifiche che vengono inviate quando l'utente esegue azioni specifiche su un elemento della sequenza temporale o quando la posizione dell'utente è stata aggiornata. Quando ti abboni a una notifica, fornisci un URL di callback che la elabora.

Ricezione di notifiche

Una notifica dall'API Mirror viene inviata come richiesta POST all'endpoint sottoscritto contenente un corpo della richiesta JSON.

HTTP non elaborato

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

Il servizio deve rispondere all'API con un codice di stato HTTP 200 OK se non si è verificato alcun errore. Se il servizio risponde con un codice di errore, l'API Mirror potrebbe provare a inviare di nuovo la notifica al servizio.

Tipi di notifiche

L'API Mirror invia un payload di notifica diverso per eventi diversi.

Risposta

L'utente ha risposto alla tua voce di cronologia utilizzando la voce di menu REPLY integrata:

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

L'attributo itemId è impostato sul valore ID dell'articolo che contiene:

  • Attributo inReplyTo impostato su ID dell'elemento della sequenza temporale a cui è una risposta.
  • Attributo text impostato sulla trascrizione del testo.
  • Attributo recipients impostato su creator dell'elemento della sequenza temporale a cui si tratta di una risposta, se esistente.

Esempio:

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

Eliminazione

L'utente ha eliminato un elemento della cronologia:

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

L'attributo itemId è impostato sull'ID dell'elemento eliminato. L'elemento non contiene più metadati diversi dal suo ID e dalla proprietà isDeleted.

Voce di menu personalizzata selezionata

L'utente ha selezionato una voce di menu personalizzata impostata dal tuo servizio:

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

L'attributo itemId è impostato sull'ID della voce di menu selezionata dall'utente.

L'array userActions contiene l'elenco delle azioni personalizzate eseguite dall'utente su questo elemento. Il tuo servizio dovrebbe gestire queste azioni di conseguenza.

Aggiornamento posizione

È disponibile una nuova posizione per l'utente corrente:

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

Quando il tuo Glassware riceve un aggiornamento della posizione, invia una richiesta all'endpoint glass.locations.get per recuperare l'ultima posizione nota. Glassware riceve aggiornamenti sulla posizione ogni dieci minuti.

Comando vocale

L'utente ha attivato un comando vocale, ad esempio: "Hey Glass, scrivi una nota, Cat Stream, il compleanno di Chipotle è domani". Viene inviata la seguente notifica al tuo Glassware:

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

Questa notifica si distingue dalle altre per il valore LAUNCH nella proprietà userActions.

Puoi quindi utilizzare il valore in itemId per recuperare l'elemento della sequenza temporale:

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

La proprietà recipients contiene il id del contatto che rappresenta il comando vocale utilizzato.