Puedes insertar, actualizar, leer y borrar tarjetas estáticas con APIs de REST simples. Además, puedes adjuntar objetos a una tarjeta estática, como una ubicación o contenido multimedia.
Cómo funcionan
De forma predeterminada, las tarjetas estáticas se encuentran a la derecha del reloj de Glass y muestran información relevante para el usuario en el momento de la entrega. Sin embargo, no requieren atención inmediata como las tarjetas en vivo y los usuarios pueden elegir leer la tarjeta o realizar acciones en ella cuando lo deseen.

Cuando Glassware inserta tarjetas estáticas en el cronograma, Glass puede reproducir un sonido de notificación para alertar a los usuarios. Todas las tarjetas estáticas anteriores también se desplazan hacia la derecha y desaparecen del cronograma después de 7 días o cuando hay 200 tarjetas más nuevas.
Cuándo usarlos
Las tarjetas estáticas son ideales para enviar
notificaciones periódicas
a los usuarios cuando suceden cosas importantes.
Por ejemplo, un servicio de entrega de noticias que envía las noticias más importantes a medida que suceden. Las tarjetas estáticas de la API de Mirror
también pueden iniciar tarjetas en vivo o
inmersiones a través del
OPEN_URI
elemento de menú. Esto te permite crear interacciones híbridas que utilizan tarjetas estáticas como notificaciones y una tarjeta en vivo o inmersión para una experiencia más interactiva.
Para obtener una lista completa de las operaciones posibles para los elementos del cronograma, consulta la documentación de referencia.
Cómo insertar tarjetas estáticas
Para insertar tarjetas estáticas (elementos del cronograma), POST una representación JSON de un elemento del cronograma en el extremo REST.
La mayoría de los campos de un elemento del cronograma son opcionales. En su forma más sencilla, un elemento del cronograma solo contiene un mensaje de texto corto, como en este ejemplo:
HTTP sin procesar
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()
Si la operación se realiza correctamente, recibirás un código de respuesta 201 Created con una copia completa del elemento creado. En el ejemplo anterior, una respuesta correcta podría verse de la siguiente manera:
HTTP sin procesar
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"
}
El elemento insertado que aparecería en el cronograma del usuario se ve de la siguiente manera:

Cómo insertar un elemento del cronograma con un archivo adjunto
Una imagen vale más que mil palabras, que es mucho más de lo que puedes incluir en un elemento del cronograma. Para ello, también puedes adjuntar imágenes y videos a un elemento del cronograma. Este es un ejemplo de cómo insertar un elemento del cronograma con una foto adjunta:
HTTP sin procesar
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 del cronograma con una imagen adjunta se ve de la siguiente manera en Glass:

Cómo adjuntar video
Si adjuntas archivos de video a los elementos del cronograma, te recomendamos que transmitas el video en lugar de subir toda la carga útil a la vez. La API de Google Mirror admite la transmisión con HTTP Live Streaming, la descarga progresiva y el protocolo de transmisión en tiempo real (RTSP). Los firewalls suelen bloquear RTSP, por lo que debes usar las otras opciones cuando sea posible.
Para transmitir video, usa el PLAY_VIDEO
elemento de menú integrado y especifica que la URL del video sea el
payload. Consulta
Cómo agregar elementos de menú integrados y
formatos de contenido multimedia admitidos
para obtener más información.
Paginación
Puedes paginar los elementos del cronograma que no caben en una sola tarjeta del cronograma, pero que, de lo contrario, deberían asociarse con la misma tarjeta. Todos los elementos paginados
comparten el mismo timeline.id y, por lo tanto, tienen el
mismo conjunto de elementos de menú. Cuando un usuario presiona un elemento del cronograma paginado, aparece un elemento de menú Leer más.
Glass pagina automáticamente los elementos del cronograma que muestran
text. Para que Glass pagine automáticamente
html, usa la article
etiqueta con su propiedad de clase establecida en auto-paginate como en el siguiente ejemplo:
<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>
Para paginar manualmente, usa la etiqueta article para el contenido que deseas mostrar en cada tarjeta. Glass muestra el contenido de cada etiqueta article en una tarjeta de subcronograma independiente. Por ejemplo, puedes crear un elemento del cronograma paginado con el siguiente 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>
De forma predeterminada, la primera tarjeta del elemento del cronograma paginado se muestra como la tarjeta de portada y se vuelve a mostrar cuando el usuario selecciona el elemento de menú Leer más. Para evitar que la primera tarjeta vuelva a aparecer después de presionar
Leer más, puedes especificar la cover-only clase CSS para la primera
<article> etiqueta:
<article class="cover-only">
...
La clase cover-only también admite elementos del cronograma paginados automáticamente:
<article class="auto-paginate cover-only">
...
Agrupación
La agrupación te permite agrupar elementos relacionados, pero distintos, como mensajes individuales en un hilo de correo electrónico. Los paquetes tienen una tarjeta de portada principal que un usuario presiona para mostrar un subcronograma que contiene las otras tarjetas del paquete. Los paquetes se distinguen de las tarjetas normales del cronograma por un pliegue de esquina en la esquina superior derecha de la tarjeta de portada del paquete.
Para agrupar elementos del cronograma, créalos con el mismo valor para
bundleId. El elemento agregado más recientemente es la tarjeta de portada del paquete.
En las siguientes imágenes, se muestra una tarjeta de portada del paquete con el pliegue de esquina en la esquina superior derecha y dos tarjetas agrupadas debajo de ella.


Cómo leer elementos del cronograma
Tu servicio puede acceder a todos los elementos del cronograma que creó y a todos los elementos del cronograma que se compartieron con él. Sigue estos pasos para enumerar los elementos del cronograma que son visibles para tu servicio.
HTTP sin procesar
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()
Puedes usar otras operaciones de REST para obtener, actualizar y borrar elementos del cronograma.
Cómo acceder a los archivos adjuntos
Puedes acceder a los archivos adjuntos de un elemento del cronograma a través
de una propiedad de array llamada attachments.
Luego, puedes obtener los datos binarios de un archivo adjunto a través de la
contentUrl
propiedad del archivo adjunto o con el
endpoint de archivos adjuntos.
HTTP sin procesar
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();
Cómo crear elementos de menú
Los elementos de menú permiten a los usuarios solicitar acciones relacionadas con la tarjeta del cronograma y se presentan en dos tipos: elementos de menú integrados y elementos de menú personalizados.
Los elementos de menú integrados proporcionan acceso a funcionalidades especiales que proporciona Glass, como leer una tarjeta del cronograma en voz alta, navegar a una ubicación, compartir una imagen o responder un mensaje:

Los elementos de menú personalizados permiten que tu aplicación exponga un comportamiento específico de tu Glassware, y también puedes proporcionar un ícono de elemento de menú que coincida con tu marca.
Cómo agregar elementos de menú integrados
Puedes agregar elementos de menú integrados a los elementos del cronograma propagando el
menuItems array cuando los insertas.
Para usar un elemento de menú integrado, solo debes propagar el
action de cada menuItem.
HTTP sin procesar
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"
}
]
}
Cómo definir elementos de menú personalizados
Si los elementos de menú integrados no te funcionan, puedes crear elementos de menú personalizados con tus propias acciones haciendo lo siguiente cuando insertes o actualices un elemento del cronograma:
- Especifica
CUSTOMparamenuItem.action. - Especifica un
menuItem.id. Cuando los usuarios presionan el elemento de menú personalizado, tu Glassware recibe una notificación conmenuItem.idpropagado. Esto te permite determinar la fuente de la notificación. - Especifica
menuItem.valuespara agregar uniconUrly undisplayNameque aparezcan en Glass. Apunta a una imagen PNG de 50 x 50 que sea de color blanco con un fondo transparente para eliconUrl. Especifica un
displayTime. Si no especificas undisplayTime, el elemento del cronograma se mueve al frente del cronograma cada vez que los usuarios presionan el elemento de menú personalizado.
HTTP sin procesar
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"
}]
}
]
}
Cómo permitir que los usuarios fijen tu tarjeta del cronograma
Puedes crear un elemento de menú que permita a los usuarios fijar la tarjeta del cronograma, que muestra de forma permanente la tarjeta del cronograma a la izquierda de la tarjeta del reloj principal. Los usuarios también pueden desafijar la tarjeta con el mismo elemento de menú.
El elemento de menú de fijación es un elemento de menú integrado, por lo que solo debes proporcionar el TOGGLE_PINNED
action para un menuItem.
HTTP sin procesar
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"
}
...
]
}
Suscripciones
La API de Mirror te permite suscribirte a las notificaciones que se envían cuando el usuario realiza acciones específicas en un elemento del cronograma o cuando se actualiza la ubicación del usuario. Cuando te suscribes a una notificación, proporcionas una URL de devolución de llamada que procesa la notificación.
Recibir notificaciones
Se envía una notificación de la API de Mirror como una solicitud POST al extremo suscrito que contiene un cuerpo de solicitud JSON.
HTTP sin procesar
{
"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)
Tu servicio debe responder a la API con un código de estado HTTP 200 OK si no se produjo ningún error.
Si tu servicio responde con un código de error, la API de Mirror podría intentar volver a enviar la notificación a tu servicio.
Tipos de notificación
La API de Mirror envía una carga útil de notificación diferente para diferentes eventos.
Responder
El usuario respondió tu elemento del cronograma con el elemento de menú integrado REPLY:
{
"collection": "timeline",
"itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
"operation": "INSERT",
"userToken": "harold_penguin",
"verifyToken": "random_hash_to_verify_referer",
"userActions": [
{
"type": "REPLY"
}
]
}
El atributo itemId se establece en el ID del elemento que contiene lo siguiente:
- Atributo
inReplyToestablecido en elIDdel elemento del cronograma al que responde - Atributo
textestablecido en la transcripción de texto - Atributo
recipientsestablecido en elcreatordel elemento del cronograma al que responde, si existe
Ejemplo:
{
"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"
]
}
]
}
Borrar
El usuario borró un elemento del cronograma:
{
"collection": "timeline",
"itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
"operation": "DELETE",
"userToken": "harold_penguin",
"verifyToken": "random_hash_to_verify_referer",
"userActions": [
{
"type": "DELETE"
}
]
}
El atributo itemId se establece en el ID del elemento borrado. El elemento ya no contiene metadatos que no sean su ID y la
isDeleted propiedad.
Elemento de menú personalizado seleccionado
El usuario seleccionó un elemento de menú personalizado establecido por tu servicio:
{
"collection": "timeline",
"itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
"operation": "UPDATE",
"userToken": "harold_penguin",
"userActions": [
{
"type": "CUSTOM",
"payload": "PING"
}
]
}
El atributo itemId se establece en el ID del elemento de menú que seleccionó el usuario.
El array userActions contiene la lista de acciones personalizadas que el usuario realizó en este elemento. Tu servicio debe controlar esas acciones en consecuencia.
Ubicación actualizada
Hay una nueva ubicación disponible para el usuario actual:
{
"collection": "locations",
"itemId": "latest",
"operation": "UPDATE",
"userToken": "harold_penguin",
"verifyToken": "random_hash_to_verify_referer"
}
Cuando tu Glassware recibe una ubicación actualizada, envía una solicitud al glass.locations.get para recuperar la ubicación más reciente conocida. Tu Glassware recibe actualizaciones de ubicación cada diez minutos.
Comando por voz
Tu usuario activó un comando por voz, por ejemplo: "Ok Glass, toma una nota, Cat Stream, el cumpleaños de Chipotle es mañana". Se envía la siguiente notificación a tu Glassware:
{
"collection": "timeline",
"operation": "INSERT",
"userToken": "chipotle's_owner",
"verifyToken": "mew mew mew",
"itemId": "<ITEM_ID>",
"userActions": [
{“type”: "LAUNCH"}
]
}
Esta notificación se distingue de otras notificaciones por el valor LAUNCH
en la userActions propiedad.
Luego, puedes usar el valor en itemId para recuperar el elemento del cronograma:
{
"id": "<ITEM_ID>",
"text": "Chipotle's birthday is tomorrow",
"recipients": [
{"id": "CAT_STREAM"}
]
}
La propiedad recipients contiene el id del contacto que representa el comando por voz utilizado.