第 3 步:添加闹钟和通知

在此步骤中,您将学习以下内容:

  • 如何按指定的时间间隔唤醒应用以执行后台任务。
  • 如何使用屏幕通知吸引用户注意一些重要信息。

完成此步骤的预计用时:20 分钟。 如需预览您要在此步骤中完成的内容,请跳转到此页面的底部 ↓

使用提醒功能增强 Todo 应用

添加相应功能,在用户有打开的待办事项时(即使应用已关闭)提醒用户,从而改进待办事项应用。

首先,您需要为应用添加一种方法来定期检查未完成的待办事项。接下来,应用需要向用户显示一条消息,即使 Todo 应用窗口已关闭。为此,您需要了解闹钟和通知在 Chrome 应用中的工作原理。

添加闹钟

使用 chrome.alarms 设置起床时间间隔。只要 Chrome 仍在运行,就会按照大致设定的时间间隔调用闹钟监听器。

更新应用权限

manifest.json 中,请求 "alarms" 权限:

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

更新后台脚本

background.js 中,添加 onAlarm 监听器。目前,每当有待办事项时,回调函数只会向控制台记录一条消息:

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

更新 HTML 视图

index.html 中,添加激活闹钟按钮:

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

现在,您需要为这个新按钮编写 JavaScript 事件处理脚本。回想一下,在第 2 步中提到,内嵌 JavaScript 导致了最常见的 CSP 违规行为之一。在 index.html 中,添加此行以导入将在下一步中创建的新 alarms.js 文件:

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

创建闹钟脚本

js 文件夹中创建一个名为 alarms.js 的新文件。

使用以下代码添加 checkAlarm()createAlarm()cancelAlarm()toggleAlarm() 方法,以及点击事件处理脚本,以便在点击“启用闹钟”按钮时开启/关闭闹钟。

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

重新加载应用,然后花一点时间激活(和停用)闹钟。

检查后台网页消息

启用闹钟后,每次闹钟“响铃”时,您应该会看到控制台中输出了日志消息:

输出到控制台的警报消息

您会发现:

  • 即使你关闭了待办事项应用窗口,闹钟仍会响起。
  • 在 ChromeOS 以外的平台上,如果您完全关闭所有 Chrome 浏览器实例,将不会触发闹钟。

我们来逐一了解 alarms.js 中使用 chrome.alarms 方法的部分代码。

创建闹钟

createAlarm() 中,使用 chrome.alarms.create() API 在启用闹钟切换开关时创建闹钟。

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

第一个参数是一个可选字符串,用于标识闹钟的唯一名称,例如 remindme。(注意:您需要设置闹钟名称,才能按名称取消闹钟。)

第二个参数是 alarmInfo 对象。alarmInfo 的有效属性包括 whendelayInMinutes 以及 periodInMinutes。为了减少用户计算机的负载,Chrome 将闹钟限制为每分钟一次。我们在这里使用较小值(每分钟 0.1 分钟)仅用于演示目的。

清除闹钟

cancelAlarm() 中,使用 chrome.alarms.clear() API,以便在取消闹钟切换开关时取消闹钟。

chrome.alarms.clear(alarmName);

第一个参数应该是您在 chrome.alarms.create() 中用作闹钟名称的标识字符串。

第二个(可选)参数是一个回调函数,其格式应为:

function(boolean wasCleared) {...};

设置闹钟

checkAlarm() 中,使用 chrome.alarms.getAll() API 获取已创建的所有闹钟的数组,以便更新切换按钮的界面状态。

getAll() 接受传入 Alarm 对象数组的回调函数。如需查看 Alarm 中的内容,您可以在开发者工具控制台中检查正在运行的闹钟,如下所示:

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

这将输出一个对象,例如 {name: "remindme", periodInMinutes: 0.1, scheduledTime: 1397587981166.858},如下所示:

使用 getAll() 检查正在运行的闹钟。

为下一部分做好准备

现在,闹钟已设置好即可定期轮询应用,接下来可以以此为基础来添加视觉通知。

添加通知

我们将闹钟通知更改为用户能够轻松注意到的内容。使用 chrome.notifications 显示如下桌面通知:

我们的待办事项应用通知

当用户点击通知时,“待办事项”应用窗口应该会进入视图。

更新应用权限

manifest.json 中,请求 "notifications" 权限:

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

更新后台脚本

background.js 中,将 chrome.app.window.create() 回调重构为一个独立的方法,以便您可以重复使用它:

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

更新闹钟监听器

background.js 顶部,为警报监听器中使用的数据库名称添加一个变量:

var dbName = 'todos-vanillajs';

dbName 的值与 js/app.js 第 17 行中设置的数据库名称相同:

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

创建通知

更新 onAlarm 监听器以通过 chrome.storage.local.get() 获取存储的数据并调用 showNotification() 方法,而不是简单地将新闹钟记录到控制台:

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

将此 showNotification() 方法添加到 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()会检查是否有待处理(未完成)的待办事项。如果至少有一个待处理的待办事项,请通过 chrome.notifications.create() 创建弹出式通知。

第一个参数是唯一标识通知名称。您必须设置 ID,才能清除或处理与该特定通知的互动。如果该 ID 与现有通知匹配,create() 会先清除该通知,然后再发出新通知。

第二个参数是 NotificationOptions 对象。呈现通知弹出式窗口的选项有很多。这里我们使用的是“基本”通知,其中包含图标、标题和消息。其他通知类型包括图片、列表和进度指示器。完成第 3 步并尝试其他通知功能后,您可以随时返回本部分。

第三个(可选)参数是回调方法,其格式如下:

function(string notificationId) {...};

处理通知交互

在用户点击通知时打开待办事项应用。在 background.js 末尾,创建一个 chrome.notifications.onClicked 事件处理脚本:

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

事件处理脚本回调只会调用 launch() 方法。chrome.app.window.create() 会创建一个新的 Chrome 应用窗口(如果尚无该窗口),或聚焦于当前打开且窗口 ID 为 main 的窗口。

启动已完成的待办事项应用

您已完成第 3 步!立即重新加载提醒应用。

检查以下行为是否符合预期:

  • 如果没有任何未完成的待办事项,系统不会显示弹出式通知。
  • 如果您在应用关闭时点击通知,Todo 应用会打开或获得焦点。

问题排查

最终的 background.js 文件应如下所示。如果未显示通知,请确认您的 Chrome 是版本 28 或更高版本。如果通知仍未显示,请在开发者工具控制台中检查主窗口(右键点击 > Inspect Element)和背景页面(点击右键点击 > Inspect Background Page)上的错误消息。

更多信息

如需详细了解此步骤中引入的一些 API,请参阅:

准备好继续下一步了吗?转到第 4 步 - 使用 WebView 打开外部链接 »