Schede statiche

Puoi inserire, aggiornare, leggere ed eliminare le schede statiche utilizzando semplici API REST. Inoltre, puoi allegare oggetti a una scheda statica, ad esempio una località o contenuti multimediali.

Funzionamento

Per impostazione predefinita, le schede statiche si trovano a destra dell'orologio di Glass e mostrano informazioni pertinenti per l'utente al momento della pubblicazione. Tuttavia, non richiedono un'attenzione immediata come le schede live e gli utenti possono scegliere di leggere o agire sulla 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 200 schede sono più recenti.

Quando utilizzarle

Le schede statiche sono ideali per inviare notifiche periodiche agli utenti quando si verificano eventi importanti. Ad esempio, un servizio di distribuzione di notizie che invia le principali notizie man mano che si verificano. Le schede statiche dell'API Mirror possono anche avviare schede live o immersioni tramite la voce di menu OPEN_URI. In questo modo puoi creare interazioni ibride che utilizzano schede statiche come notifiche e una scheda live o un'immersione 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 sequenza temporale), invia una rappresentazione JSON di un elemento della sequenza temporale a ll'endpoint REST.

La maggior parte dei campi di un elemento della sequenza temporale sono facoltativi. 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()

In caso di esito positivo, ricevi un codice di risposta 201 Created con una copia completa dell'elemento creato. Per l'esempio precedente, una risposta riuscita potrebbe essere simile alla seguente:

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 verrà visualizzato nella sequenza temporale dell'utente è il seguente:

Inserimento di un elemento della sequenza temporale con un allegato

Un'immagine vale più di mille parole, ovvero molto più di quanto puoi inserire in un elemento della sequenza temporale. A questo scopo, 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 su Glass è simile al seguente:

Allegare video

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

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

Paginazione

Puoi paginare gli elementi della sequenza temporale che non rientrano in una singola scheda della sequenza temporale, ma che altrimenti dovrebbero essere associati alla stessa scheda. Tutti gli elementi paginati condividono lo stesso timeline.id e pertanto hanno lo stesso insieme di voci di menu. Quando un utente tocca un elemento della sequenza temporale paginato, viene visualizzata una voce di menu Leggi di più.

Glass impagina automaticamente gli elementi della sequenza temporale che mostrano text. Per fare in modo che Glass impagini automaticamente html, utilizza il article tag 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 che vuoi visualizzare su ogni scheda. Glass mostra i contenuti di ogni tag article in una scheda della sequenza temporale secondaria separata. Ad esempio, puoi creare un elemento della sequenza temporale paginato 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 paginato viene visualizzata come scheda di copertina e viene visualizzata di nuovo quando l'utente seleziona la voce di menu Leggi di più. Per impedire che la prima scheda venga visualizzata di nuovo dopo aver toccato Leggi di più, puoi specificare la classe CSS cover-only per il primo <article> tag:

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

La classe cover-only supporta anche gli elementi della sequenza temporale con impaginazione automatica:

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

Raggruppamento

Il raggruppamento ti consente di raggruppare elementi correlati ma distinti, ad esempio i singoli messaggi in una conversazione via email. I bundle hanno una scheda di copertina principale che un utente tocca per visualizzare una sequenza temporale secondaria che contiene le altre schede del bundle. I bundle si distinguono dalle normali schede della sequenza temporale per una piega 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 bundle.

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

Lettura degli elementi della sequenza temporale

Il tuo servizio può accedere a tutti gli elementi della sequenza temporale che ha creato e a tutti gli elementi della sequenza temporale che sono stati condivisi con esso. 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 ottenere, aggiornare e eliminare gli elementi della sequenza temporale.

Accesso agli allegati

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

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 forniscono l'accesso a funzionalità speciali fornite da Glass, come la lettura ad alta voce di una scheda della sequenza temporale, la navigazione verso una località, 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 che corrisponda al tuo brand.

Aggiunta di voci di menu integrate

Puoi aggiungere voci di menu integrate agli elementi della sequenza temporale compilando il menuItems array quando li inserisci. Per utilizzare una voce di menu integrata, devi solo compilare il 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 sono adatte alle tue esigenze, puoi creare voci di menu personalizzate con le tue azioni procedendo nel seguente modo quando inserisci o aggiorni un elemento della sequenza temporale:

  • Specifica CUSTOM per menuItem.action.
  • Specifica un menuItem.id. Quando gli utenti toccano la voce di menu personalizzata, il tuo Glassware riceve una notifica con menuItem.id compilato. In questo modo puoi determinare l'origine della notifica.
  • Specifica menuItem.values per aggiungere un iconUrl e un displayName che viene visualizzato su Glass. Punta a un'immagine PNG 50 x 50 di colore bianco con uno sfondo trasparente per iconUrl.
  • Specifica un displayTime. Se non specifichi un displayTime, l'elemento della sequenza temporale si sposta 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 appuntare la scheda della sequenza temporale

Puoi creare una voce di menu che consenta agli utenti di appuntare la scheda della sequenza temporale, che visualizza in modo permanente la scheda della sequenza temporale a sinistra della scheda dell'orologio principale. Gli utenti possono anche disancorare la scheda utilizzando la stessa voce di menu.

La voce di menu di ancoraggio è una voce di menu integrata, quindi devi solo fornire il TOGGLE_PINNED action per un 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 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 elabora la notifica.

Ricezione di notifiche.

Una notifica dell'API Mirror viene inviata come richiesta POST all'endpoint a cui è stato effettuato l'abbonamento 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 tuo servizio deve rispondere all'API con un codice di stato HTTP 200 OK se non si è verificato alcun errore. Se il tuo servizio risponde con un codice di errore, l'API Mirror potrebbe provare a inviare nuovamente la notifica al tuo servizio.

Tipi di notifiche

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

Rispondi

L'utente ha risposto all'elemento della sequenza temporale utilizzando la voce di menu integrata REPLY:

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

L'attributo itemId è impostato sull'ID dell'elemento contenente:

  • L'attributo inReplyTo è impostato sull'ID dell'elemento della sequenza temporale a cui si riferisce la risposta.
  • L'attributo text è impostato sulla trascrizione del testo.
  • L'attributo recipients è impostato sul creator dell'elemento della sequenza temporale a cui si riferisce la risposta, 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 dall'ID e dalla isDeleted proprietà.

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 deve gestire queste azioni di conseguenza.

Aggiornamento della 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'glass.locations.get glass.locations.get per recuperare l'ultima posizione nota. Il tuo Glassware riceve aggiornamenti della posizione ogni dieci minuti.

Comando vocale

L'utente ha attivato un comando vocale, ad esempio: "Ok Glass, prendi nota, Cat Stream, il compleanno di Chipotle è domani". Al tuo Glassware 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 notifiche per il LAUNCH valore nella userActions proprietà.

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 l'id del contatto che rappresenta il comando vocale utilizzato.