Paso 3: Agrega alarmas y notificaciones

En este paso, aprenderás lo siguiente:

  • Cómo activar tu app en intervalos específicos para ejecutar tareas en segundo plano
  • Cómo usar las notificaciones en pantalla para llamar la atención sobre algo importante

Tiempo estimado para completar este paso: 20 minutos Para obtener una vista previa de lo que completarás en este paso, ve hasta la parte inferior de esta página ↓.

Mejora tu app de tareas pendientes con recordatorios

Mejora la app de tareas pendientes agregando funcionalidad para recordarle al usuario si tiene tareas pendientes abiertas, incluso cuando la app está cerrada.

En primer lugar, debes agregar una forma para que la app verifique con regularidad si hay tareas pendientes no completadas. A continuación, la app debe mostrarle un mensaje al usuario, incluso si se cierra la ventana de la app de Tareas pendientes. Para lograrlo, debes comprender cómo funcionan las alarmas y las notificaciones en las apps de Chrome.

Agregar alarmas

Usa chrome.alarms para establecer un intervalo de activación. Mientras Chrome esté en ejecución, se llamará al objeto de escucha de alarmas aproximadamente el intervalo establecido.

Actualiza los permisos de la app

En manifest.json, solicita el permiso "alarms":

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

Actualiza las secuencias de comandos en segundo plano

En background.js, agrega un objeto de escucha onAlarm. Por ahora, la función de devolución de llamada solo registrará un mensaje en la consola cada vez que haya un elemento pendiente:

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

Cómo actualizar la vista HTML

En index.html, agrega un botón Activar alarma:

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

Ahora, debes escribir el controlador de eventos de JavaScript para este nuevo botón. Recuerda del paso 2 que uno de los incumplimientos de CSP más comunes se debe a JavaScript intercalado. En index.html, agrega esta línea para importar un nuevo archivo alarms.js que crearás en el siguiente paso:

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

Crear secuencia de comandos de alarmas

Crea un archivo nuevo en la carpeta js llamado alarms.js.

Usa el siguiente código para agregar los métodos checkAlarm(), createAlarm(), cancelAlarm() y toggleAlarm(), junto con un controlador de eventos de clic para activar o desactivar la alarma cuando se hace clic en el botón Activar alarma.

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

Vuelve a cargar la app y activa (y desactiva) la alarma durante unos minutos.

Cómo inspeccionar mensajes de página en segundo plano

Siempre que la alarma esté activada, deberías ver mensajes de registro impresos en la consola cada vez que la alarma "suena":

Mensajes de alarma que se imprimen en la consola

Deberías notar lo siguiente:

  • Incluso cuando cierres la ventana de la app de Tareas pendientes, las alarmas seguirán sonando.
  • En plataformas que no sean ChromeOS, si cierras todas las instancias del navegador Chrome por completo, las alarmas no se activarán.

Analicemos algunas de las partes de alarms.js que usan métodos chrome.alarms una por una.

Crear alarmas

En createAlarm(), usa la API de chrome.alarms.create() para crear una alarma cuando esté activada la opción Activar alarma.

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

El primer parámetro es una string opcional que identifica un nombre único para tu alarma, por ejemplo, remindme. (Nota: Debes establecer un nombre de alarma para poder cancelarla por nombre).

El segundo parámetro es un objeto alarmInfo. Las propiedades válidas para alarmInfo incluyen when o delayInMinutes, y periodInMinutes. Para reducir la carga en la máquina del usuario, Chrome limita las alarmas a una vez por minuto. Usamos valores pequeños (0.1 de un minuto) aquí solo con fines de demostración.

Borrar alarmas

En cancelAlarm(), usa la API de chrome.alarms.clear() para cancelar una alarma cuando esté activado Cancelar alarma.

chrome.alarms.clear(alarmName);

El primer parámetro debe ser la string de identificación que usaste como nombre de alarma en chrome.alarms.create().

El segundo parámetro (opcional) es una función de devolución de llamada que debe adoptar el siguiente formato:

function(boolean wasCleared) {...};

Recibe alarmas

En checkAlarm(), usa la API de chrome.alarms.getAll() para obtener un array de todas las alarmas creadas a fin de actualizar el estado de la IU del botón de activación.

getAll() acepta una función de devolución de llamada que pasa un array de objetos Alarm. Para ver el contenido de una Alarm, puedes inspeccionar alarmas en ejecución en la consola de Herramientas para desarrolladores de la siguiente manera:

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

Esto generará un objeto como {name: "remindme", periodInMinutes: 0.1, scheduledTime: 1397587981166.858}, como se muestra a continuación:

Usa getAll() para inspeccionar las alarmas en ejecución.

Prepárate para la siguiente sección

Ahora que se implementaron alarmas para sondear la app a intervalos regulares, usa esto como base para agregar notificaciones visuales.

Agregar notificaciones

Cambiemos la notificación de la alarma por algo que el usuario pueda notar con facilidad. Usa chrome.notifications para mostrar una notificación de escritorio como la que se muestra a continuación:

Nuestra notificación de la app de tareas pendientes

Cuando el usuario hace clic en la notificación, debería aparecer la ventana de la app de tareas pendientes.

Actualiza los permisos de la app

En manifest.json, solicita el permiso "notifications":

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

Actualiza las secuencias de comandos en segundo plano

En background.js, refactoriza la devolución de llamada chrome.app.window.create() en un método independiente para que puedas volver a usarla:

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

Actualizar objeto de escucha de alarmas

En la parte superior de background.js, agrega una variable para el nombre de una base de datos que se usa en el objeto de escucha de la alarma:

var dbName = 'todos-vanillajs';

El valor de dbName es el mismo nombre de base de datos que se estableció en la línea 17 de js/app.js:

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

Cómo crear una notificación

En lugar de registrar una alarma nueva en Console, actualiza el objeto de escucha onAlarm para obtener datos almacenados a través de chrome.storage.local.get() y llama a un método showNotification():

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

Agrega 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);
...

showNotification() buscará elementos pendientes abiertos (sin completar). Si hay al menos un elemento pendiente, crea una ventana emergente de notificación mediante chrome.notifications.create().

El primer parámetro es un nombre de notificación que identifica de manera inequívoca. Debes tener un ID establecido para borrar o controlar las interacciones con esa notificación en particular. Si el ID coincide con una notificación existente, create() primero borra esa notificación antes de crear una nueva.

El segundo parámetro es un objeto NotificationOptions. Hay muchas opciones para renderizar la ventana emergente de la notificación. Aquí usamos una notificación “básica” con un ícono, un título y un mensaje. Otros tipos de notificaciones incluyen imágenes, listas e indicadores de progreso. Puedes volver a esta sección cuando termines el paso 3 y experimentes con otras funciones de notificaciones.

El tercer parámetro (opcional) es un método de devolución de llamada que debe adoptar el siguiente formato:

function(string notificationId) {...};

Cómo controlar las interacciones de las notificaciones

Abre la app de Todo cuando el usuario haga clic en la notificación. Al final de background.js, crea un controlador de eventos chrome.notifications.onClicked:

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

La devolución de llamada del controlador de eventos simplemente llama al método launch(). chrome.app.window.create() crea una nueva ventana de la app de Chrome, si aún no existe, o pone en foco la ventana abierta actualmente con el ID de ventana main.

Inicia tu app de tareas pendientes terminada

Has terminado el paso 3. Vuelve a cargar tu app de tareas pendientes ahora con recordatorios.

Comprueba que estos comportamientos funcionen como se espera:

  • Si no tienes elementos de tareas pendientes sin completar, no verás notificaciones emergentes.
  • Si haces clic en la notificación cuando la app está cerrada, la app de tareas pendientes se abrirá o se enfocará.

Solución de problemas

El archivo final background.js debería verse así. Si no aparecen las notificaciones, confirma que tu versión de Chrome sea la 28 o posterior. Si aún no se muestran las notificaciones, comprueba si hay mensajes de error en la consola de Herramientas para desarrolladores, tanto en la ventana principal (clic con el botón derecho > Inspeccionar elemento) como en la página en segundo plano (clic derecho > Inspeccionar página en segundo plano).

Más información

Para obtener información más detallada sobre algunas de las APIs presentadas en este paso, consulta lo siguiente:

¿Todo listo para continuar con el siguiente paso? Ir al Paso 4: Abre vínculos externos con una vista web »