Schede statiche

Puoi inserire, aggiornare, leggere ed eliminare schede statiche utilizzando API REST semplici. Inoltre, puoi collegare gli oggetti a una scheda statica, ad esempio una posizione o i contenuti multimediali.

Funzionamento

Le schede statiche si trovano a destra dell'orologio di vetro per impostazione predefinita e mostrano informazioni pertinenti all'utente al momento della consegna. Tuttavia, non richiedono attenzione immediata come le schede pubblicate e gli utenti possono scegliere di leggere o utilizzare la scheda quando preferiscono.

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 a destra e scompaiono dalla sequenza temporale dopo 7 giorni o quando le 200 schede sono più recenti.

Quando utilizzarli

Le schede statiche sono ottime per inviare notifiche periodiche agli utenti quando si verificano eventi importanti. Ad esempio, un servizio di distribuzione delle notizie che invia le notizie principali non appena si verificano. Le schede statiche dell'API Mirroring possono anche avviare schede pubblicate o coinvolgimento tramite la voce di menu OPEN_URI. In questo modo puoi creare interazioni ibride che utilizzano le schede statiche come notifiche e una scheda in tempo reale o un'interazione 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 le schede statiche (elementi della sequenza temporale), POSTA una rappresentazione JSON di un elemento della sequenza temporale nell'endpoint REST.

La maggior parte dei campi di un elemento nella sequenza temporale è facoltativa. Nella sua forma più semplice, un elemento della sequenza temporale contiene solo un breve SMS, come nell'esempio seguente:

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 è andata a buon fine, 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 appare nella sequenza temporale dell'utente ha il seguente aspetto:

Inserire un elemento della sequenza temporale con un allegato

Un'immagine vale mille parole, molto di più di quelle che puoi inserire in un elemento della sequenza temporale. A questo scopo, puoi anche allegare immagini e video a un elemento della sequenza temporale. Di seguito è riportato 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 è simile a questa su Glass:

Allegare video

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

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

Impaginazione

Puoi impaginare le voci della sequenza temporale che non rientrano in una singola scheda della sequenza temporale, ma devono essere associate alla stessa scheda. Gli elementi impaginati hanno tutti la stessa timeline.id e pertanto hanno lo stesso insieme di voci di menu. Quando un utente tocca una voce della sequenza temporale impaginata, viene visualizzata una voce di menu Ulteriori informazioni.

Glass impagina automaticamente gli elementi della sequenza temporale che mostrano text. Per fare in modo che Glass impagina automaticamente html, utilizza il tag article con la proprietà class 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 da visualizzare in ciascuna scheda. Glass visualizza i contenuti di ogni tag article in una scheda di Spostamenti separata. Ad esempio, puoi creare un elemento della sequenza temporale 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 viene visualizzata come scheda di copertina e nuovamente quando l'utente seleziona la voce di menu Ulteriori informazioni. Per evitare che la prima scheda venga visualizzata di nuovo dopo aver toccato Ulteriori informazioni, 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 con pagine automatiche:

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

Pacchettizzazione

Il raggruppamento ti consente di raggruppare elementi correlati ma separati, ad esempio per singoli messaggi in un thread di email. I pacchetti presentano una scheda di copertina principale che un utente tocca per visualizzare una sequenza temporale che contiene le altre schede. I pacchetti si distinguono dalle normali schede della sequenza temporale per un angolo piegato nell'angolo in alto a destra della scheda di copertina.

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

Le seguenti immagini mostrano una scheda di copertina in bundle con l'angolo piegato nell'angolo in alto a destra e due schede in bundle sotto.

Lettura degli elementi della sequenza temporale

Il servizio può accedere a tutti gli elementi della sequenza temporale che ha creato e a tutti gli elementi della sequenza temporale con cui sono stati condivisi. Ecco come elencare gli elementi della sequenza temporale che sono 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 ricevere, aggiornare ed eliminare le voci della sequenza temporale.

Accesso agli allegati

Puoi accedere agli allegati di un elemento della sequenza temporale tramite una proprietà dell'array denominata attachments. Puoi quindi ottenere i dati binari di un allegato tramite la proprietà contentUrl dell'allegato o con 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 delle voci di menu in corso...

Le voci di menu consentono agli utenti di richiedere azioni correlate alla scheda della sequenza temporale e sono di due tipi: voci di menu integrate e voci di menu personalizzate.

Le voci di menu integrate consentono di accedere alle funzionalità speciali fornite da Glass, ad esempio la lettura ad alta voce di una scheda della sequenza temporale, la navigazione in un luogo, la condivisione di un'immagine o la risposta a un messaggio:

Le voci di menu personalizzate consentono alla tua applicazione di esporre un comportamento specifico per il tuo Glassware e puoi anche fornire un'icona della voce di menu corrispondente al tuo branding.

Aggiungere voci del menu integrate

Puoi aggiungere voci di menu integrate agli elementi della sequenza temporale compilando menuItems array quando li inserisci. Per utilizzare una voce di menu incorporata, devi completare solo action in 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 delle voci di menu personalizzate

Se le voci del menu integrate non funzionano, puoi creare voci di menu personalizzate eseguendo le tue azioni come segue quando inserisci o aggiorni una voce della sequenza temporale:

  • Specifica CUSTOM per menuItem.action.
  • Specifica un menuItem.id. Quando gli utenti toccano una voce di menu personalizzata, il tuo Glassware riceve una notifica che viene completata con menuItem.id. In questo modo puoi determinare l'origine della notifica.
  • Specifica menuItem.values per aggiungere un elemento iconUrl e displayName visualizzato su Glass. Posiziona il puntatore del mouse su un'immagine PNG 50 x 50 di colore bianco con uno sfondo trasparente per l'elemento iconUrl.
  • Specifica un displayTime. Se non specifichi un elemento displayTime, la voce della sequenza temporale viene spostata in primo piano 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 bloccare la tua scheda della cronologia

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

La voce di menu di blocco è una voce di menu incorporata, perciò devi soltanto fornire la proprietà TOGGLE_PINNED action per una 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 consente di iscriversi alle notifiche inviate quando l'utente intraprende azioni specifiche su un elemento della sequenza temporale o quando la posizione dell'utente è stata aggiornata. Quando ti iscrivi a una notifica, devi fornire un URL di callback che elabora la notifica.

Ricezione 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 nuovamente la notifica.

Tipi di notifiche

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

Rispondi

L'utente ha risposto alla tua voce della sequenza temporale 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 contenente:

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

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

Elimina

L'utente ha eliminato un elemento della sequenza temporale:

{
  "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 del menu personalizzata impostata dal 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 intraprese dall'utente per questo elemento. Il tuo servizio dovrebbe gestire tali azioni di conseguenza.

Aggiornamento posizione

È disponibile un nuovo percorso per l'utente corrente:

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

Quando il Glassware riceve un aggiornamento della posizione, invia una richiesta all'endpoint glass.locations.get per recuperare la posizione nota più recente. Il tuo Glassware riceve gli aggiornamenti sulla posizione ogni dieci minuti.

Comando vocale

L'utente ha attivato un comando vocale, ad esempio: "Ok Glass, crea una nota, Cat Stream, il compleanno di Chipotle è domani domani". Al tuo Glasswareware viene inviata la seguente notifica:

{
  "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 del tag 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.