Etapa 3: adicionar alarmes e notificações

Nesta etapa, você vai aprender:

  • Como ativar seu app em intervalos especificados para executar tarefas em segundo plano.
  • Como usar as notificações na tela para chamar a atenção para algo importante.

Tempo estimado para concluir esta etapa: 20 minutos. Para ter uma prévia do que você vai concluir nesta etapa, pule até o final desta página ↓.

Melhore seu app Todo com lembretes

Melhore o app Todo adicionando uma funcionalidade para lembrar o usuário se ele tiver tarefas abertas, mesmo quando o app estiver fechado.

Primeiro, você precisa adicionar uma maneira para que o app verifique regularmente se há tarefas não concluídas. Em seguida, o app precisa mostrar uma mensagem para o usuário, mesmo que a janela do app Todo esteja fechada. Para fazer isso, você precisa entender como os alarmes e notificações funcionam nos apps do Chrome.

Adicionar alarmes

Use chrome.alarms para definir um intervalo de ativação. Enquanto o Chrome estiver em execução, o listener de alarme será chamado aproximadamente no intervalo definido.

Atualizar as permissões de aplicativos

No manifest.json, solicite a permissão "alarms":

"permissions": ["storage", "alarms"],

Atualizar scripts em segundo plano

Em background.js, adicione um listener onAlarm. Por enquanto, a função de callback registrará apenas uma mensagem no Console sempre que houver um item de lista de tarefas:

chrome.app.runtime.onLaunched.addListener(function() {
  chrome.app.window.create('index.html', {
    id: 'main',
    bounds: { width: 620, height: 500 }
  });
});
chrome.alarms.onAlarm.addListener(function( alarm ) {
  console.log("Got an alarm!", alarm);
});

Atualizar visualização HTML

Em index.html, adicione um botão Ativar alarme:

<footer id="info">
  <button id="toggleAlarm">Activate alarm</button>
  ...
</footer>

Agora você precisa criar o manipulador de eventos JavaScript para esse novo botão. Lembre-se da Etapa 2 que uma das não conformidades mais comuns da CSP é causada pelo JavaScript in-line. Em index.html, adicione esta linha para importar um novo arquivo alarms.js que você criará na seguinte etapa:

  </footer>
  ...
  <script src="js/app.js"></script>
  <script src="js/alarms.js"></script>
</body>

Criar script de alarmes

Crie um novo arquivo na pasta js com o nome alarms.js.

Use o código abaixo para adicionar os métodos checkAlarm(), createAlarm(), cancelAlarm() e toggleAlarm(), com um manipulador de eventos de clique para alternar o alarme quando o botão Ativar alarme for clicado.

(function () {
  'use strict';
   var alarmName = 'remindme';
   function checkAlarm(callback) {
     chrome.alarms.getAll(function(alarms) {
       var hasAlarm = alarms.some(function(a) {
         return a.name == alarmName;
       });
       var newLabel;
       if (hasAlarm) {
         newLabel = 'Cancel alarm';
       } else {
         newLabel = 'Activate alarm';
       }
       document.getElementById('toggleAlarm').innerText = newLabel;
       if (callback) callback(hasAlarm);
     })
   }
   function createAlarm() {
     chrome.alarms.create(alarmName, {
       delayInMinutes: 0.1, periodInMinutes: 0.1});
   }
   function cancelAlarm() {
     chrome.alarms.clear(alarmName);
   }
   function doToggleAlarm() {
     checkAlarm( function(hasAlarm) {
       if (hasAlarm) {
         cancelAlarm();
       } else {
         createAlarm();
       }
       checkAlarm();
     });
   }
  $$('#toggleAlarm').addEventListener('click', doToggleAlarm);
  checkAlarm();
})();

Atualize o app e ative (e desative) o alarme por alguns instantes.

Inspecionar mensagens em segundo plano

.

Sempre que o alarme estiver ativado, você vai ver mensagens de registro impressas no console toda vez que o alarme "tocar":

Impressão de mensagens de alarme no console

Você vai notar que:

  • Mesmo quando você fecha a janela do app Todo, os alarmes continuam chegando.
  • Em outras plataformas que não o ChromeOS, se você fechar completamente todas as instâncias do navegador Chrome, os alarmes não serão acionados.

Vamos analisar algumas das partes em alarms.js que usam métodos chrome.alarms, um a um.

Criar alarmes

Em createAlarm(), use a API chrome.alarms.create() para criar um alarme quando a opção Ativar alarme for ativada.

chrome.alarms.create(alarmName, {delayInMinutes: 0.1, periodInMinutes: 0.1});

O primeiro parâmetro é uma string opcional que identifica um nome exclusivo para o alarme, por exemplo, remindme. (Observação: é necessário definir um nome de alarme para poder cancelá-lo pelo nome.)

O segundo parâmetro é um objeto alarmInfo. As propriedades válidas para alarmInfo incluem when ou delayInMinutes e periodInMinutes. Para reduzir a carga na máquina do usuário, o Chrome limita os alarmes a uma vez por minuto. Estamos usando valores pequenos (0,1 de um minuto) apenas para fins de demonstração.

Limpar alarmes

Em cancelAlarm(), use a API chrome.alarms.clear() para cancelar um alarme quando a opção Cancelar alarme estiver ativada.

chrome.alarms.clear(alarmName);

O primeiro parâmetro precisa ser a string de identificação que você usou como nome de alarme em chrome.alarms.create().

O segundo parâmetro (opcional) é uma função de callback que precisa seguir o formato:

function(boolean wasCleared) {...};

Receber alarmes

Em checkAlarm(), use a API chrome.alarms.getAll() para acessar uma matriz de todos os alarmes criados e atualizar o estado do botão de ativação na interface.

getAll() aceita uma função de callback que transmite uma matriz de objetos Alarm. Para ver o que há em uma Alarm, você pode inspecionar os alarmes em execução no Console do DevTools desta forma:

chrome.alarms.getAll(function(alarms) {
  console.log(alarms);
  console.log(alarms[0]);
});

Isso vai gerar um objeto como {name: "remindme", periodInMinutes: 0.1, scheduledTime: 1397587981166.858}, conforme mostrado abaixo:

Use getAll() para inspecionar alarmes em execução.

Prepare-se para a próxima seção

Agora que os alarmes estão configurados para pesquisar o app em intervalos regulares, use isso como base para adicionar notificações visuais.

Adicionar notificações

Vamos alterar a notificação de alarme para algo que o usuário possa notar facilmente. Use chrome.notifications para mostrar uma notificação na área de trabalho como a abaixo:

Notificação do app Todo

Quando o usuário clica na notificação, a janela do app Todo deve ser exibida.

Atualizar as permissões de aplicativos

No manifest.json, solicite a permissão "notifications":

"permissions": ["storage", "alarms", "notifications"],

Atualizar scripts em segundo plano

Em background.js, refatore o callback chrome.app.window.create() em um método autônomo para que seja possível reutilizá-lo:

chrome.app.runtime.onLaunched.addListener(function() {
function launch() {
  chrome.app.window.create('index.html', {
    id: 'main',
    bounds: { width: 620, height: 500 }
  });
}
});
chrome.app.runtime.onLaunched.addListener(launch);
...

Atualizar listener de alarmes

Na parte superior do background.js, adicione uma variável para um nome de banco de dados usado no listener de alarmes:

var dbName = 'todos-vanillajs';

O valor de dbName é o mesmo nome de banco de dados definido na linha 17 de js/app.js:

var todo = new Todo('todos-vanillajs');

Criar uma notificação

Em vez de simplesmente registrar um novo alarme no Console, atualize o listener onAlarm para receber dados armazenados usando chrome.storage.local.get() e chame um método showNotification():

chrome.alarms.onAlarm.addListener(function( alarm ) {
  console.log("Got an alarm!", alarm);
  chrome.storage.local.get(dbName, showNotification);
});

Adicione este método showNotification() a background.js:

function launch(){
  ...
}

function showNotification(storedData) {
  var openTodos = 0;
  if ( storedData[dbName].todos ) {
    storedData[dbName].todos.forEach(function(todo) {
      if ( !todo.completed ) {
        openTodos++;
      }
    });
  }
  if (openTodos>0) {
    // Now create the notification
    chrome.notifications.create('reminder', {
        type: 'basic',
        iconUrl: 'icon_128.png',
        title: 'Don\'t forget!',
        message: 'You have '+openTodos+' things to do. Wake up, dude!'
     }, function(notificationId) {});
  }
}

chrome.app.runtime.onLaunched.addListener(launch);
...

O showNotification() vai verificar se há itens abertos (não concluídos). Se houver pelo menos um item de tarefas abertos, crie um pop-up de notificação usando o chrome.notifications.create().

O primeiro parâmetro é um nome de notificação de identificação exclusiva. Você precisa ter um ID definido para limpar ou processar interações com essa notificação específica. Se o ID corresponder a uma notificação existente, o create() limpará essa notificação antes de criar uma nova.

O segundo parâmetro é um objeto NotificationOptions. Há muitas opções para renderizar o pop-up de notificação. Aqui, estamos usando uma notificação "básica" com um ícone, um título e uma mensagem. Outros tipos de notificação incluem imagens, listas e indicadores de progresso. Volte a esta seção quando concluir a Etapa 3 e teste outros recursos de notificação.

O terceiro parâmetro (opcional) é um método de callback que precisa seguir o formato:

function(string notificationId) {...};

Gerenciar interações de notificação

Abrir o app Todo quando o usuário clicar na notificação. No final de background.js, crie um manipulador de eventos chrome.notifications.onClicked:

chrome.notifications.onClicked.addListener(function() {
  launch();
});

O callback do manipulador de eventos simplesmente chama o método launch(). chrome.app.window.create() cria uma nova janela de apps do Chrome, se ainda não existir, ou coloca o foco na janela aberta no momento que tem o ID de janela main.

Iniciar o app Todo concluído

Você concluiu a Etapa 3! Atualize o app Todo agora com lembretes.

Verifique se estes comportamentos funcionam conforme o esperado:

  • Se você não tiver nenhum item do Google Atividades não concluído, não vai haver notificações pop-up.
  • Se você clicar na notificação quando o app for fechado, o app Todo será aberto ou entrará em foco.

Solução de problemas

Seu arquivo background.js final terá esta aparência. Se as notificações não estiverem aparecendo, confirme se a versão do Chrome é a 28 ou mais recente. Se as notificações ainda não aparecerem, verifique se há mensagens de erro no Console do DevTools na janela principal (clique com o botão direito do mouse > Inspecionar elemento) e na página de fundo (clique com o botão direito do mouse > Inspect Background Page).

Mais informações

Para informações mais detalhadas sobre algumas das APIs introduzidas nesta etapa, consulte:

Tudo pronto para passar à próxima etapa? Vá para a Etapa 4: abrir links externos com um WebView »