起床囉!我的手機寶貝!– Alarm API 的使用與介紹

功能簡介

Alarm API 最初是為了 FireFox OS (FFOS) 所特別開發的一種 Web API,可以在預定時間自動喚醒系統去執行特定作業;這種功能可以套用在許多實際的應用上,最容易聯想到的功能就是 Alarm Clock 的應用,有了這個 API 我們就可以要求 FFOS 在某個時間點,讓裝置自動產生振動或是鬧鈴來通知使用者,藉此實現一個 Alarm Clock Application (App) 的功能。但 Alarm API 並不只如字面上地專為 Alarm Clock App 所設計,舉例來說,E-Mail App 也可以藉由 Alarm API 讓系統每隔一段時間就主動去 server 上下載最新郵件;Calendar App 可以讓系統在預約的日期提醒使用者參加會議;Auto-Update App 可以定期驅動系統去檢查、下載並安裝軟體更新。

對於很多 App 開發者來說,你們一定會很好奇,Alarm API 到底與一般 Javascript 裡的 setTimeout(...) 函式有何不同?setTimeout(...) 不也可以讓我們在某個時間點去執行某段 callback function 嗎?最大的不同點就在於,setTimeout(...) 必須在系統「醒著」的時候才有效用,這對很多行動作業系統來說,其實是一項天生的限制,因為智慧型手機為了更有效地做到省電的功能,會讓系統在沒人使用的時候,進入所謂的「睡眠模式」(Sleep Mode),此時 CPU 會處於完全停止運作的狀態,而無法執行 setTimeout(...) 裡的 callback function,造成 setTimeout(...) 暫時失效,除非直到使用者下次將系統手動喚醒,callback function 才會再度被執行,但此時早已過了預定時間。為了解決這個問題,Alarm API 因此孕育而生,它可以藉由 Kernel 底層的機制(註一)將系統直接喚醒,繼續執行使用者預先所設定的 callback function,做到真正的「準時」。或許我們應該將 Alarm API 重新命名成一個更通用的名字叫 Wake-Up API,因為他不只是帶有一個 alarm 所必需的「準時」概念,還有將系統從「睡眠模式」移轉到「待機模式」(Standby Mode) 的功能。

如何使用

Alarm API 的介面定義如下:

partial interface Navigator
{
    readonly attribute AlarmsManager mozAlarms;
};

interface AlarmsManager
{
    DOMRequest add(in jsval date,
                   in DOMString respectTimezone,
                   [optional] in jsval data);
    DOMRequest getAll();
    void remove(in unsigned long id);
};

要使用 Alarm API 註冊一個 alarm 其實很簡單,下面以程式碼片段的方式介紹 add(...) 函式的基本用法,我們可以利用第一個參數加入一個在「2012 年 5 月 15 日下午 4 點 20 分」喚醒系統的 alarm,並且利用第三個參數帶入一個 JSON object 去描述關於此 alarm 的附屬資訊(如範例中的 { mydata: "bar" }),這個 JSON object 將在 alarm 執行 callback function 時以參數的形式一同返回。此外,我們必須利用第二個參數設定此 alarm 關於 timezone 的屬性,我們可以指定 "ignoreTimezone" 或是 "honorTimezone";使用 "ignoreTimezone" 表示此 alarm 將在「當地時區」的下午 4 點 20 分喚醒系統,也就是說,alarm 會隨者當下系統時區的不同,調整其 alarm 醒來的「相對時間」,例如:紐約時間的下午 4 點 20 分和巴黎時間的下午 4 點 20 分是兩個不一樣的絕對時間;使用 "honorTimezone" 表示此 alarm 將在使用者設定此 alarm 時「所處時區」的下午 4 點 20 分喚醒系統,這將會是一個固定的「絕對時間」,例如:使用者在紐約設定了一個下午 4 點 20 分的 alarm,如果使用者之後帶著他的手機到巴黎,此 alarm 將會在巴黎時間的上午 10 點 20 分醒來(註二)。

var alarmId;
var req = navigator.mozAlarms.add(
    new Date("May 15, 2012 16:20:00"),
    "ignoreTimezone", { mydata: "bar" });
req.onsuccess = function (e) {
    alarmId1 = e.target.result;
};
req.onerror = function (e) {
    alert(e.target.error.name);
};

另外,我們可以使用 getAll() 函式來取得我們曾經為此 App 所設定過的 alarms 資訊:

var req = navigator.mozAlarms.getAll();
req.onsuccess = function (e) {
    alert(JSON.stringify(e.target.result));
};
req.onerror = function (e) {
    alert(e.target.error.name);
};

我們也可以利用 remove(...) 配合 add(...) 所回傳的 ID 來取消我們曾經設定過的 alarm:

navigator.mozAlarms.remove(alarmId);

最後,我們將介紹如何註冊一個 alarm 喚醒系統時所需執行的 callback function。要做到這點,我們必須使用另外一個 Web API 的機制,稱作 System Message API,我們可以利用 mozSetMessageHandler(...) 函式的第一個參數去註冊一個名為 "alarm" 的 system message type,之後,每當同一個 App 的 alarm 醒來時,系統就會執行第二個參數所綁定的 callback function(註三),此時,App 開發者可以參考當初使用 add(...) 在第三個參數所帶入的 JSON object 資訊,來決定其 callback function 對此 alarm 所需執行的相對應行為。

navigator.mozSetMessageHandler(
    "alarm",
    function (msg) {
        alert(JSON.stringify(msg));
    }
);

期待您的回饋

在初步階段,Alarm API 只能在裝載有 FFOS 的行動裝置上使用,我們正在努力將 Alarm API 支援各種 OS 平台,包括 Windows、Linux、Android 以及 Cocoa。更多關於 Alarm API 的使用細節請參考註四中的連結,在此也歡迎您提出任何寶貴的建議與相關問題。在未來,Mozilla 也會持續將 Alarm API 的設計與使用心得回饋給 World Wide Web Consortium (W3C),致力使它成為一個公開且正式的 W3C Web API(註五)。

註釋與參考

註一:Android 的 Linux Kernel 有提供 Wake Lock 機制,可以確保 CPU 保持在運轉狀態。
註二:巴黎所處的 timezone 比紐約所處的 timezone 快 6 個小時。
註三:System Message API 不在此文的討論範圍內,更多使用細節請參考註四連結中的範例。
註四:Alarm API – https://wiki.mozilla.org/WebAPI/AlarmAPI
註五:Web Alarms API Specification – http://www.w3.org/TR/web-alarms/