今天,我們正式跨入專案的第三階段。過去十八天的所有努力——從學習 JS 語法、設計資料結構、打造動態 UI,到征服非同步程式設計——都是為了這一刻所做的準備。
我們即將接觸的,是整個專案的核心技術:Web Bluetooth API。這是一套內建於現代瀏覽器中,功能極其強大的工具集,它賦予了我們用網頁程式碼與周遭物理世界的藍牙裝置直接溝通的能力 。
然而,俗話說:「能力越強,責任越大」。為了保護使用者的安全與隱私,瀏覽器對這項強大的能力設定了非常嚴格的使用規則。你不能隨意地在使用者不知情的情況下,掃描或控制他們身邊的裝置。
因此,在我們寫下第一行真正的 API 呼叫之前,今天的任務,就是先
學習這本「使用者手冊」,徹底理解使用 Web Bluetooth API 的三大黃金法則。理解並遵守這些規則,不是一個選項,而是我們能成功寫出任何功能程式碼的絕對前提 。
在開始學習規則之前,我們先理解「為什麼」要有這些規則。
保護隱私:如果任何網站都能隨意掃描藍牙,惡意網站就可以透過你隨身攜帶的藍牙耳機、健身手環等裝置來追蹤你的位置,這將是嚴重的隱私洩漏。
保障安全:想像一下,如果一個網頁可以在你不知情的情況下,連接並控制你的智慧門鎖或醫療設備,後果將不堪設想。
因此,Web Bluetooth API 的設計核心理念就是「使用者知情並明確同意」。接下來的所有規則,都圍繞著這個核心展開。
要成功呼叫 Web Bluetooth API,你必須同時滿足以下三個缺一不可的條件。
這是什麼意思?:你的網頁必須是透過 HTTPS 協定載入的。在瀏覽器網址列,你會看到一個 🔒 鎖頭圖示。
為什麼需要?:HTTPS 能加密你的瀏覽器和網站伺服器之間的通訊,確保沒有中間人可以竊聽或篡改你們的通訊內容。要求在 HTTPS 環境下使用,是為了防止駭客在不安全的 Wi-Fi 網路中,攔截你的網頁指令,並冒充你的網頁向藍牙裝置發送惡意命令。
**對我們開發的影響 :
如果你是直接在檔案總管中點兩下打開 index.html
,網址會是 file:///...
。在這種情況下,Web Bluetooth API 絕對無法運作!
在本地開發時,現代瀏覽器通常會將 http://localhost
或 http://127.0.0.1
視為一個安全上下文,所以我們可以在這個環境下進行開發和測試。
解決方案:使用像 VS Code 的 "Live Server" 這類工具,它可以輕鬆地幫你在 localhost
上啟動一個本地伺服器。
這是什麼意思?:呼叫掃描功能 navigator.bluetooth.requestDevice()
的這行程式碼,必須是在一個由使用者主動發起的事件中執行的。最常見的例子就是點擊 (click
) 按鈕。
為什麼需要?:這是獲取使用者「明確同意」的關鍵。瀏覽器不會允許一個網站在使用者剛載入頁面時,就自動彈出一個藍牙權限請求視窗。必須是使用者自己點了「掃描」、「連接」之類的按鈕,瀏覽器才會認為:「好的,使用者現在想要進行藍牙操作了」,並彈出掃描視窗。
對我們開發的影響:這完美地解釋了為什麼我們之前要花時間去學習 scanButton.onclick
事件監聽。我們所有藍牙相關的探索流程,都必須從這個 onclick
函式內部開始。
這是什麼意思?:Web Bluetooth API 仍然是一項相對較新的技術,並不是所有瀏覽器都支援它。
目前支援情況 (截至 2025 年):
桌面端:Chrome、Edge、Opera 在 Windows、macOS、Linux 和 ChromeOS 上支援良好。
行動端:Android 上的 Chrome 支援良好。
不支援:Firefox 目前不支援。iOS (iPhone/iPad) 上的所有瀏覽器 (包括 Chrome) 都不支援,這是最需要注意的一點。macOS 上的 Safari 支援部分功能。
對我們開發的影響:一個健壯的應用程式,不應該在不支援的瀏覽器上直接崩潰。專業的做法是,在執行任何藍牙程式碼之前,先檢查瀏覽器是否支援此 API。
了解了規則後,讓我們把「檢查規則」這件事寫成程式碼。這就像飛行員在起飛前,需要檢查儀表板一樣。
打開 app.js
,找到我們之前寫的 scanButton.onclick
函式,並將其更新為以下內容:
// app.js
// ... (我們之前選取 DOM 元素和定義 UI 函式的程式碼) ...
// 更新 scanButton 的 onclick 事件處理器
scanButton.onclick = async () => {
// 法則三:檢查瀏覽器是否支援 Web Bluetooth API
if (!navigator.bluetooth) {
const errorMsg = '很抱歉,您的瀏覽器不支援 Web Bluetooth API。';
statusText.textContent = errorMsg;
console.error(errorMsg);
// 如果不支援,就直接結束,不往下執行
return;
}
// 如果程式碼能執行到這裡,代表至少瀏覽器是支援的
// 並且因為這段程式碼是在 click 事件中,也滿足了法則二 (使用者手勢)
// 法則一 (HTTPS) 則由瀏覽器在呼叫 API 時自動檢查
console.log('瀏覽器支援 Web Bluetooth API!');
statusText.textContent = '準備掃描...';
try {
// 明天,我們將在這裡寫下真正的掃描程式碼...
console.log('即將呼叫 requestDevice()...');
// const device = await navigator.bluetooth.requestDevice(...);
} catch(error) {
console.error('發生錯誤:', error);
statusText.textContent = `錯誤: ${error.message}`;
}
};
navigator.bluetooth
是 Web Bluetooth API 的入口物件。如果瀏覽器不支援,navigator.bluetooth
這個物件就不會存在(其值為 undefined
)。透過 !navigator.bluetooth
就可以判斷是否支援。如果不支援,我們就更新狀態文字、在控制台報錯,並用 return
提前終止函式的執行。今天,我們學習了 Web Bluetooth API 的「遊戲規則」,這是我們正式上場前的必修課。
明天,我們將在這段預檢程式碼的 try
區塊中,寫下那行我們期待已久的、真正具有魔力的程式碼:await navigator.bluetooth.requestDevice()
。我們將親眼見證瀏覽器的藍牙掃描視窗被我們的程式碼喚醒,並邁出將網頁與物理世界連結起來的、歷史性的第一步。
那麼今天的內容就到這邊,感謝你能看到這裡,在這邊祝你早安、午安、晚安,我們明天見。