É possível inserir, atualizar, ler e excluir cards estáticos usando APIs REST simples. Além disso, é possível anexar objetos a um card estático, como um local ou mídia.
Como funcionam
Os cards estáticos ficam à direita do relógio do Glass por padrão e mostram informações relevantes para o 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 ler ou agir no card quando quiserem.
Quando o Glassware insere cards estáticos na linha do tempo, o Google Glass pode tocar um som de notificação para alertar os usuários. Todos os cards estáticos anteriores também são movidos para a direita e desaparecem da linha do tempo após sete dias ou quando 200 cards são mais recentes.
Quando usar as extensões
Os cards estáticos são ótimos para enviar
notificações periódicas
aos usuários quando coisas importantes acontecem.
Por exemplo, um serviço de entrega de notícias que
envia as principais notícias conforme elas acontecem. Os cards estáticos da API Mirror também podem iniciar cards ao vivo ou imersões pelo item de menu OPEN_URI
. Isso permite criar interações híbridas que usam
cards estáticos como notificações e um card ao vivo ou imersão para
uma experiência mais interativa.
Para conferir uma lista completa de operações possíveis para itens de linha do tempo, consulte a documentação de referência.
Inserir cards estáticos
Para inserir cards estáticos (itens de linha do tempo), envie uma representação JSON de um item de linha do tempo para o endpoint REST.
A maioria dos campos em um item de 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 o procedimento for bem-sucedido, você vai receber um código de resposta 201 Created
com uma
cópia completa do item criado. No exemplo anterior, uma resposta bem-sucedida
pode ser parecida com esta:
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:
Como inserir um item de linha do tempo com um anexo
Uma imagem vale mais que mil palavras, o que é muito mais do que você pode colocar 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. Confira um exemplo de como inserir um item da linha do tempo com um anexo de foto:
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 fica assim no Glass:
Anexar vídeo
Se você estiver anexando arquivos de vídeo aos itens da linha do tempo, recomendamos que você faça streaming do vídeo em vez de enviar o payload inteiro de uma vez. A API Google Mirror oferece suporte a streaming com HTTP live streaming, download progressivo e o protocolo de streaming em tempo real (RTSP). O RTSP é frequentemente bloqueado por firewalls. Use as outras opções sempre que possível.
Para transmitir um 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 aceitos
para mais informações.
Paginação
É possível paginar itens de linha do tempo que não cabem em um único card,
mas precisam ser associados ao mesmo card. Os itens
paginados compartilham o mesmo timeline.id
e, portanto, têm o
mesmo conjunto de itens de menu. Quando um usuário toca em um item de linha do tempo paginado, um item de menu Leia mais aparece.
O Glass pagina automaticamente os itens da linha do tempo que mostram
text
. Para que o Glass paginar automaticamente
html
, use a tag article
com a propriedade de classe definida como auto-paginate
, como no exemplo abaixo:
<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 mostrar em cada card. O Glass mostra o conteúdo de cada
tag article
em um card de sublinha do tempo separada. Por exemplo, é possível criar um
item de 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 paginada é mostrado como o
card de capa e aparece novamente quando o usuário seleciona o item de menu
Read more. 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 oferece suporte a itens de linha do tempo paginados automaticamente:
<article class="auto-paginate cover-only">
...
Agrupamento
O agrupamento permite que você agrupe itens relacionados, mas distintos, como mensagens individuais em uma conversa por e-mail. Os pacotes têm um card de capa principal que o usuário toca para mostrar uma sublinha do tempo que contém os outros cards no pacote. Os pacotes são diferenciados dos cards normais da linha do tempo por uma dobra no canto superior direito do card de capa do pacote.
Para agrupar itens de linha do tempo, crie-os com o mesmo valor para
bundleId
. O item adicionado mais recentemente
é o card de capa do pacote.
As imagens a seguir mostram um cartão de capa do pacote com a dobra de canto no canto superior direito e dois cartões do pacote abaixo dele.
Como ler itens da linha do tempo
Seu serviço pode acessar todos os itens da linha do tempo que ele criou e todos os itens da linha do tempo que foram compartilhados com ele. Saiba como listar os itens da linha do tempo que estão 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 anexos de um item de linha do tempo por
uma propriedade de matriz chamada attachments
.
Depois, é possível acessar os dados binários de um anexo usando a propriedade
contentUrl
do anexo ou 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();
Criação de itens de menu
Os itens de menu permitem que os usuários solicitem ações relacionadas ao card da linha do tempo. Eles são de dois tipos: itens de menu integrados e personalizados.
Os itens de menu integrados oferecem acesso a funcionalidades especiais fornecidas pelo Glass, como ler um card da linha do tempo em voz, navegar até um local, compartilhar uma imagem ou responder a uma mensagem:
Os itens de menu personalizados permitem que o aplicativo exponha um comportamento específico para o Glassware. Você também pode fornecer um ícone de item de menu para combinar com sua marca.
Como adicionar itens de menu integrados
É possível adicionar itens de menu integrados aos itens da linha do tempo preenchendo o
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"
}
]
}
Como 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 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 Glassware recebe uma notificação commenuItem.id
preenchido. Isso permite determinar a origem da notificação. - Especifique
menuItem.values
para adicionar umiconUrl
edisplayName
que aparece no Glass. Aponte para uma imagem PNG de 50 x 50 de cor branca com um plano de fundo transparente paraiconUrl
. Especifique um
displayTime
. Se você não especificar umdisplayTime
, o item da linha do tempo será movido para a frente 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 seu card de linha do tempo
Você pode criar um item de menu que permite que os usuários fixem o card da linha do tempo, que exibe permanentemente o card da linha do tempo à esquerda do card principal. Os usuários também podem desafixar o card usando o mesmo item de menu.
O item de menu de fixação é um item de menu integrado. Portanto, basta 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 que você se inscreva em notificações que são enviadas quando o usuário realiza ações específicas em um item da linha do tempo ou quando o local do usuário é atualizado. Ao se inscrever para receber uma notificação, você informa 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 assinado 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)
Seu serviço precisa responder à API com um código de status HTTP 200 OK
se nenhum erro ocorreu.
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 eventos diferentes.
Responder
O usuário respondeu ao item da 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
é definido como o ID
do item que contém:
- O atributo
inReplyTo
é definido como oID
do item da linha do tempo a que ele é uma resposta. - Atributo
text
definido para a transcrição de texto. - Atributo
recipients
definido como ocreator
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
é 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 de menu personalizado selecionado
O usuário selecionou um item de menu personalizado definido pelo seu 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 que
o usuário selecionou.
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 adequadamente.
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 localização, envie uma solicitação para o endpoint glass.locations.get para recuperar o último local conhecido. O Glassware recebe atualizações de local a cada dez minutos.
Comando de voz
O usuário ativou um comando de voz, por exemplo: "Ok Glass, anote, 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 das 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.