Cards estáticos

É possível inserir, atualizar, ler e excluir cartões estáticos usando APIs REST simples. Além disso, é possível anexar objetos a um cartão estático, como um local ou uma mídia.

Como funcionam

Por padrão, os cartões estáticos ficam à direita do relógio Glass e exibem informações relevantes ao usuário no momento da entrega. No entanto, eles não exigem atenção imediata, como os cards ao vivo, e os usuários podem optar por ler ou realizar ações no cartão quando quiserem.

Quando o Glassware insere cartões estáticos na linha do tempo, ele pode emitir um som de notificação para alertar os usuários. Todos os cartões estáticos anteriores também são deslocados para a direita e desaparecem da linha do tempo após sete dias ou quando 200 cartões são mais novos.

Quando usar os recursos

Os cartões estáticos são ótimos para enviar notificações periódicas aos usuários conforme acontecem importantes. Por exemplo, um serviço de notícias que envia as principais notícias à medida que elas acontecem. Os cartões estáticos da API Mirror também podem iniciar cards ativos ou imersões no item de menu OPEN_URI. Isso permite criar interações híbridas que usam cards estáticos como notificações e um card ativo ou imersão para oferecer uma experiência mais interativa.

Para ver uma lista completa das possíveis operações para itens da linha do tempo, consulte a documentação de referência.

Inserir cards estáticos

Para inserir cartões estáticos (itens de linha do tempo), poste uma representação JSON de um item da linha do tempo no endpoint REST.

A maioria dos campos em um item da linha do tempo é opcional. Na forma mais simples, um item da linha do tempo contém apenas uma mensagem de texto curta, como neste exemplo:

HTTP bruto

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 for bem-sucedido, você receberá um código de resposta 201 Created com uma cópia completa do item criado. No exemplo anterior, uma resposta bem-sucedida poderia ser assim:

HTTP bruto

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

O item inserido que apareceria na linha do tempo do usuário tem esta aparência:

Inserir um item da linha do tempo com um anexo

Uma imagem vale mais do que mil palavras, o que é muito mais do que a capacidade de caber em um item da linha do tempo. Para isso, você também pode anexar imagens e vídeos a um item da linha do tempo. Veja um exemplo de como inserir um item da linha do tempo com uma foto anexada:

HTTP bruto

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

Um item da linha do tempo com uma imagem anexada é parecido com este exemplo no Google Glass:

Anexando vídeo

Se você estiver anexando arquivos de vídeo aos seus itens de linha do tempo, recomendamos fazer streaming do vídeo em vez de fazer upload de todo o payload de uma só vez. A API Google Mirror é compatível com streaming HTTP ao vivo, download progressivo e protocolo de streaming em tempo real (RTSP, na sigla em inglês). O RTSP é frequentemente bloqueado por firewalls. Portanto, use as outras opções sempre que possível.

Para fazer streaming de vídeo, use o item de menu integrado PLAY_VIDEO e especifique o URL do vídeo como o payload do item de menu. Consulte Como adicionar itens de menu integrados e formatos de mídia compatíveis para ver mais informações.

Paginação

É possível paginar itens da linha do tempo que não cabem em um único card, mas que precisam ser associados ao mesmo cartão. Todos os itens paginados compartilham o mesmo timeline.id e têm o mesmo conjunto de itens de menu. Quando um usuário toca em um item da linha do tempo paginado, um item do menu Ler mais é exibido.

O Glass pagina automaticamente os itens da linha do tempo que exibem text. Para que o Glass faça a paginação automática da html, use a tag article com a propriedade de classe definida como auto-paginate, como no exemplo a seguir:

<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, use a tag article para o conteúdo que você quer exibir em cada card. O Google Glass mostra o conteúdo de cada tag article em um card de sublinhado separado. Por exemplo, é possível criar um item da linha do tempo paginado com o seguinte 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>

Por padrão, o primeiro card do item da linha do tempo paginado é exibido como o card de capa e novamente quando o usuário seleciona o item de menu Leia mais. Para evitar que o primeiro card apareça novamente depois de tocar em Leia mais, especifique a classe CSS cover-only para a primeira tag <article>:

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

A classe cover-only também é compatível com itens de linha do tempo paginados automaticamente:

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

Pacotes

O agrupamento permite agrupar itens relacionados, mas distintos, como para mensagens individuais em uma conversa de e-mail. Os pacotes têm um card de capa principal em que um usuário toca para exibir uma linha do tempo com os outros cards do pacote. Os pacotes são diferenciados dos cards de linha do tempo normais por uma dobra no canto superior direito do card de capa do pacote.

Para agrupar itens da linha do tempo, crie-os com o mesmo valor para bundleId. O item adicionado mais recentemente é o cartão de capa do pacote.

As imagens a seguir mostram um card de capa do pacote com a dobra no canto superior direito e dois cards agrupados abaixo dele.

Ler os itens da linha do tempo

O serviço pode acessar todos os itens da linha do tempo criados e todos os que foram compartilhados com ele. Veja como listar os itens da linha do tempo visíveis para seu serviço.

HTTP bruto

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

É possível usar outras operações REST para receber, atualizar e excluir itens da linha do tempo.

Como acessar anexos

É possível acessar os anexos de um item da linha do tempo usando uma propriedade de matriz chamada attachments. É possível acessar os dados binários de um anexo por meio da propriedade contentUrl do anexo ou com o endpoint de anexos.

HTTP bruto

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

Como criar itens de menu

Os itens de menu permitem que os usuários solicitem ações relacionadas ao card da linha do tempo e são divididos em dois tipos: itens de menu integrados e personalizados.

Os itens de menu integrados oferecem acesso a recursos especiais fornecidos pelo Glass, como ler um card da linha do tempo em voz alta, navegar até um local, compartilhar uma imagem ou responder a uma mensagem:

Os itens de menu personalizados permitem que o app exponha um comportamento específico ao seu Glassware, e você também pode fornecer um ícone de item de menu que corresponda ao seu branding.

Como adicionar itens de menu integrados

É possível adicionar itens de menu integrados aos itens da linha do tempo preenchendo a menuItems array ao inseri-los. Para usar um item de menu integrado, basta preencher o action de cada menuItem.

HTTP bruto

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

Definir itens de menu personalizados

Se os itens de menu integrados não funcionarem para você, crie itens de menu personalizados com suas próprias ações fazendo o seguinte ao inserir ou atualizar um item da linha do tempo:

  • Especifique CUSTOM para menuItem.action.
  • Especifique um menuItem.id. Quando os usuários tocam no item de menu personalizado, o Glass recebe uma notificação com menuItem.id preenchido. Isso permite determinar a origem da notificação.
  • Especifique menuItem.values para adicionar um iconUrl e um displayName que aparece no Google Glass. Aponte para uma imagem PNG de 50 x 50 em branco com um plano de fundo transparente para o iconUrl.
  • Especifique um displayTime. Se você não especificar um displayTime, o item da linha do tempo vai ser exibido na frente da linha do tempo sempre que os usuários tocarem no item de menu personalizado.

HTTP bruto

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

Permitir que os usuários fixem o card da linha do tempo

Você pode criar um item de menu que permita aos usuários fixar o card da linha do tempo, que o exibe permanentemente à esquerda do card do relógio principal. Os usuários também podem liberar o cartão usando o mesmo item de menu.

O item de menu de fixação é um item integrado que você precisa fornecer o TOGGLE_PINNED action para um menuItem.

HTTP bruto

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

Inscrições

A API Mirror permite assinar notificações que são enviadas quando o usuário realiza ações específicas em um item da linha do tempo ou quando a localização do usuário é atualizada. Ao se inscrever em uma notificação, você fornece um URL de callback que processa a notificação.

Como receber notificações

Uma notificação da API Mirror é enviada como uma solicitação POST para o endpoint inscrito que contém um corpo de solicitação JSON.

HTTP bruto

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

Caso nenhum erro tenha ocorrido, seu serviço precisa responder à API com um código de status HTTP 200 OK. Se o serviço responder com um código de erro, a API Mirror poderá tentar reenviar a notificação para o serviço.

Tipos de notificação

A API Mirror envia um payload de notificação diferente para diferentes eventos.

Responder

O usuário respondeu ao item de linha do tempo usando o item de menu REPLY integrado:

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

O atributo itemId está definido como o ID do item que contém:

  • Atributo inReplyTo definido como o ID do item da linha do tempo a que ele é uma resposta.
  • Atributo text definido como a transcrição do texto.
  • Atributo recipients definido como creator do item da linha do tempo a que ele é uma resposta, se existir.

Exemplo:

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

Excluir

O usuário excluiu um item da linha do tempo:

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

O atributo itemId está definido como o ID do item excluído. O item não contém mais metadados além do ID e da propriedade isDeleted.

Item personalizado do menu selecionado

O usuário selecionou um item de menu personalizado definido pelo serviço:

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

O atributo itemId é definido como o ID do item de menu selecionado pelo usuário.

A matriz userActions contém a lista de ações personalizadas que o usuário realizou nesse item. Seu serviço precisa processar essas ações de acordo com isso.

Atualização de local

Um novo local está disponível para o usuário atual:

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

Quando o Glassware receber uma atualização de local, envie uma solicitação ao endpoint glass.locations.get para recuperar o local conhecido mais recente. Seu Glassware recebe atualizações de localização a cada 10 minutos.

Comando de voz

O usuário ativou um comando de voz, por exemplo: "Ok Glass, crie uma nota, Cat Stream, o aniversário do Chipotle é amanhã". A notificação a seguir é enviada para o Glassware:

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

Essa notificação é diferenciada de outras pelo valor LAUNCH na propriedade userActions.

Em seguida, use o valor em itemId para buscar o item da linha do tempo:

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

A propriedade recipients contém o id do contato que representa o comando de voz usado.