Cartes statiques

Vous pouvez insérer, mettre à jour, lire et supprimer des cartes statiques à l'aide d'API REST simples. Vous pouvez également joindre des objets à une carte statique, comme un lieu ou un élément multimédia.

Fonctionnement

Par défaut, les cartes statiques se trouvent à droite de l'horloge Glass et affichent des informations pertinentes pour l'utilisateur au moment de la diffusion. Toutefois, elles ne nécessitent pas d'attention immédiate comme les fiches en direct. Les utilisateurs peuvent choisir de les lire ou d'y répondre à leur guise.

Lorsque des applications Glassware insèrent des cartes statiques dans la timeline, Glass peut émettre un son de notification pour alerter les utilisateurs. Toutes les cartes statiques précédentes se déplacent également vers la droite et disparaissent de la timeline au bout de sept jours ou lorsqu'il y a 200 cartes plus récentes.

Quand les utiliser

Les cartes statiques sont idéales pour envoyer des notifications périodiques aux utilisateurs lorsque des événements importants se produisent. Par exemple, un service de diffusion d'actualités qui envoie les principaux titres de l'actualité au fur et à mesure. Les cartes statiques de l'API Mirror peuvent également lancer des cartes dynamiques ou des immersions via l'élément de menu OPEN_URI. Cela vous permet de créer des interactions hybrides qui utilisent des cartes statiques comme notifications et une carte en direct ou une immersion pour une expérience plus interactive.

Pour obtenir la liste complète des opérations possibles pour les éléments de la chronologie, consultez la documentation de référence.

Insérer des cartes statiques

Pour insérer des cartes statiques (éléments de la timeline), envoyez une représentation JSON d'un élément de la timeline au point de terminaison REST.

La plupart des champs d'un élément de la chronologie sont facultatifs. Dans sa forme la plus simple, un élément de la timeline ne contient qu'un court message texte, comme dans cet exemple :

HTTP brut

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

En cas de réussite, vous recevez un code de réponse 201 Created avec une copie complète de l'élément créé. Dans l'exemple précédent, une réponse réussie pourrait ressembler à ceci :

HTTP brut

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'élément inséré qui s'affiche dans la timeline de l'utilisateur se présente comme suit :

Insérer un élément de chronologie avec une pièce jointe

Une image vaut mieux qu'un long discours, ce qui est bien plus que ce que vous pouvez inclure dans un élément de chronologie. Pour ce faire, vous pouvez également joindre des images et des vidéos à un élément de chronologie. Voici un exemple d'insertion d'un élément de chronologie avec une pièce jointe photo :

HTTP brut

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

Sur Glass, un élément de la timeline avec une image jointe ressemble à ceci :

Joindre une vidéo

Si vous joignez des fichiers vidéo à vos éléments de timeline, nous vous recommandons de diffuser la vidéo en streaming au lieu d'importer l'intégralité de la charge utile en une seule fois. L'API Google Mirror est compatible avec le streaming via HTTP Live Streaming, le téléchargement progressif et le protocole de streaming en temps réel (RTSP). Le protocole RTSP étant souvent bloqué par les pare-feu, utilisez les autres options lorsque cela est possible.

Pour diffuser une vidéo, utilisez l'élément de menu intégré PLAY_VIDEO et spécifiez l'URL de la vidéo comme payload de l'élément de menu. Pour en savoir plus, consultez Ajouter des éléments de menu intégrés et Formats multimédias compatibles.

Pagination

Vous pouvez paginer les éléments de la chronologie qui ne tiennent pas sur une seule fiche, mais qui devraient être associés à la même fiche. Les éléments paginés partagent tous le même timeline.id et ont donc le même ensemble d'éléments de menu. Lorsqu'un utilisateur appuie sur un élément de la timeline paginée, un élément de menu Lire la suite s'affiche.

Glass pagine automatiquement les éléments de la timeline qui affichent text. Pour que Glass pagine automatiquement html, utilisez la balise article avec sa propriété de classe définie sur auto-paginate, comme dans l'exemple suivant :

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

Pour paginer manuellement, utilisez la balise article pour le contenu que vous souhaitez afficher sur chaque fiche. Glass affiche le contenu de chaque balise article dans une fiche de sous-chronologie distincte. Par exemple, vous pouvez créer un élément de chronologie paginé avec le code HTML suivant :

<article>
 <section>
   <p>First page</p>
 </section>
</article>

<article>
 <section>
   <p>Second page</p>
 </section>
</article>

<article>
 <section>
   <p>Third page</p>
 </section>
</article>

Par défaut, la première carte de l'élément de chronologie paginé est affichée en tant que carte de couverture et s'affiche à nouveau lorsque l'utilisateur sélectionne l'élément de menu En savoir plus. Pour empêcher la première carte de s'afficher à nouveau après avoir appuyé sur En savoir plus, vous pouvez spécifier la classe CSS cover-only pour la première balise <article> :

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

La classe cover-only est également compatible avec les éléments de chronologie à pagination automatique :

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

Regroupement

Le regroupement vous permet de regrouper des éléments distincts, mais associés, comme des messages individuels dans un fil de discussion. Les packs comportent une fiche de couverture principale sur laquelle l'utilisateur appuie pour afficher une sous-chronologie contenant les autres fiches du pack. Les packs se distinguent des fiches chronologiques normales par un pli dans l'angle supérieur droit de la fiche de couverture du pack.

Pour regrouper des éléments de la chronologie, créez-les avec la même valeur pour bundleId. Le dernier élément ajouté est la fiche de couverture du bundle.

Les images suivantes montrent une fiche de couverture de pack avec le coin plié en haut à droite et deux fiches groupées en dessous.

Lire les éléments de l'historique

Votre service peut accéder à tous les éléments de la timeline qu'il a créés et à tous ceux qui ont été partagés avec lui. Voici comment lister les éléments de la chronologie visibles par votre service.

HTTP brut

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

Vous pouvez utiliser d'autres opérations REST pour obtenir, mettre à jour et supprimer des éléments de la timeline.

Accéder aux pièces jointes

Vous pouvez accéder aux pièces jointes d'un élément de la timeline via une propriété de tableau nommée attachments. Vous pouvez ensuite obtenir les données binaires d'une pièce jointe via la propriété contentUrl de la pièce jointe ou avec le point de terminaison des pièces jointes.

HTTP brut

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

Créer des éléments de menu

Les éléments de menu permettent aux utilisateurs de demander des actions liées à la fiche de la timeline. Il existe deux types d'éléments de menu : les éléments de menu intégrés et les éléments de menu personnalisés.

Les éléments de menu intégrés permettent d'accéder à des fonctionnalités spéciales fournies par Glass, comme la lecture à voix haute d'une carte de chronologie, la navigation vers un lieu, le partage d'une image ou la réponse à un message :

Les éléments de menu personnalisés permettent à votre application d'exposer un comportement spécifique à votre Glassware. Vous pouvez également fournir une icône d'élément de menu correspondant à votre marque.

Ajouter des éléments de menu intégrés

Vous pouvez ajouter des éléments de menu intégrés à vos éléments de timeline en remplissant menuItems array lorsque vous les insérez. Pour utiliser un élément de menu intégré, il vous suffit de remplir le action de chaque menuItem.

HTTP brut

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

Définir des éléments de menu personnalisés

Si les éléments de menu intégrés ne vous conviennent pas, vous pouvez créer des éléments de menu personnalisés avec vos propres actions en procédant comme suit lorsque vous insérez ou mettez à jour un élément de chronologie :

  • Spécifiez CUSTOM pour menuItem.action.
  • Spécifiez un menuItem.id. Lorsque les utilisateurs appuient sur l'élément de menu personnalisé, votre Glassware reçoit une notification avec menuItem.id renseigné. Cela vous permet de déterminer la source de la notification.
  • Spécifiez menuItem.values pour ajouter un iconUrl et un displayName qui s'affichent sur Glass. Pointez sur une image PNG de 50 x 50 de couleur blanche avec un arrière-plan transparent pour iconUrl.
  • Spécifiez un displayTime. Si vous ne spécifiez pas de displayTime, l'élément de la chronologie se déplace au début de la chronologie chaque fois que les utilisateurs appuient sur l'élément de menu personnalisé.

HTTP brut

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

Autoriser les utilisateurs à épingler votre fiche chronologique

Vous pouvez créer un élément de menu qui permet à vos utilisateurs d'épingler la fiche "Chronologie", qui s'affiche en permanence à gauche de la fiche principale de l'horloge. Les utilisateurs peuvent également désépingler la fiche à l'aide du même élément de menu.

L'élément de menu d'épinglage est intégré. Il vous suffit donc de fournir le action TOGGLE_PINNED pour un menuItem.

HTTP brut

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

Abonnements

L'API Mirror vous permet de vous abonner aux notifications qui sont envoyées lorsque l'utilisateur effectue des actions spécifiques sur un élément de la timeline ou lorsque sa position a été mise à jour. Lorsque vous vous abonnez à une notification, vous fournissez une URL de rappel qui traite la notification.

Recevoir des notifications

Une notification de l'API Mirror est envoyée sous la forme d'une requête POST au point de terminaison auquel l'utilisateur est abonné. Elle contient un corps de requête JSON.

HTTP brut

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

Votre service doit répondre à l'API avec un code d'état HTTP 200 OK si aucune erreur ne s'est produite. Si votre service répond par un code d'erreur, l'API Mirror peut essayer de renvoyer la notification à votre service.

Types de notifications

L'API Mirror envoie une charge utile de notification différente pour chaque événement.

Répondre

L'utilisateur a répondu à votre élément de chronologie à l'aide de l'élément de menu REPLY intégré :

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

L'attribut itemId est défini sur le ID de l'élément contenant :

  • Attribut inReplyTo défini sur le ID de l'élément de chronologie auquel il répond.
  • Attribut text défini sur la transcription du texte.
  • Attribut recipients défini sur le creator de l'élément de la chronologie auquel il répond, le cas échéant.

Exemple :

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

Supprimer

L'utilisateur a supprimé un élément de la timeline :

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

L'attribut itemId est défini sur l'ID de l'élément supprimé. L'élément ne contient plus de métadonnées autres que son ID et la propriété isDeleted.

Élément de menu personnalisé sélectionné

L'utilisateur a sélectionné un élément de menu personnalisé défini par votre service :

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

L'attribut itemId est défini sur l'ID de l'élément de menu sélectionné par l'utilisateur.

Le tableau userActions contient la liste des actions personnalisées effectuées par l'utilisateur sur cet élément. Votre service doit gérer ces actions en conséquence.

Mise à jour de la position

Une nouvelle position est disponible pour l'utilisateur actuel :

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

Lorsque votre Glassware reçoit une mise à jour de la position, envoyez une requête au point de terminaison glass.locations.get pour récupérer la dernière position connue. Votre Glassware reçoit des informations sur la position toutes les dix minutes.

Commande vocale

Votre utilisateur a activé une commande vocale, par exemple : "Ok Glass, prends une note, l'anniversaire de Cat Stream chez Chipotle est demain". La notification suivante est envoyée à votre Glassware :

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

Cette notification se distingue des autres par la valeur LAUNCH dans la propriété userActions.

Vous pouvez ensuite utiliser la valeur dans itemId pour récupérer l'élément de la chronologie :

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

La propriété recipients contient le id du contact qui représente la commande vocale utilisée.