É 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
paramenuItem.action
. - Especifique um
menuItem.id
. Quando os usuários tocam no item de menu personalizado, o Glass recebe uma notificação commenuItem.id
preenchido. Isso permite determinar a origem da notificação. - Especifique
menuItem.values
para adicionar umiconUrl
e umdisplayName
que aparece no Google Glass. Aponte para uma imagem PNG de 50 x 50 em branco com um plano de fundo transparente para oiconUrl
. Especifique um
displayTime
. Se você não especificar umdisplayTime
, 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 oID
do item da linha do tempo a que ele é uma resposta. - Atributo
text
definido como a transcrição do texto. - Atributo
recipients
definido comocreator
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.