什麼是 Web NFC API? Web NFC API 是一種 Web API,允許 Progressive Web App (PWA) 在使用者裝置靠近 NFC 標籤(通常距離 5-10 公分)時,讀取或寫入 NDEF (NFC Data Exchange Format) 格式的資料。透過 NDEFReader 介面,網頁應用程式可以實現如博物館展品導覽、庫存盤點、或是馬拉松晶片感應等功能。這項技術目前僅在網頁處於「可見狀態(Visible)」時運作,以確保安全性與隱私,並嚴格限制僅能透過 HTTPS 執行。
什麼是 Web NFC? NFC (Near Field Communication) 近場通訊是高頻 (13.56 MHz) 短距離無線通訊技術,只要距離 5-10 公分內 Web NFC 就能夠讀取和寫入 NFC 標籤,傳輸速率高達 424 kbit/s。
目前 Web NFC 只支援 NDEF,尚不支援 ISO-DEP、NFC-A/B、NFC-F、HCE。
Demo 站台如下,只會示範讀取功能,因為不太確定真的執行寫入悠遊卡會不會壞掉 Orzhttps://linyencheng.github.io/pwa-web-nfc/
Web App 會透過 Page Visibility API 來偵測目前網站是否在 “可見” 的狀態,在可見狀態下才能夠執行掃描讀取或寫入。
當用戶成功使用其設備掃描 NFC 標籤時,瀏覽器會使用震動來提示。
如果螢幕關閉或設備被鎖定,則對 NFC 讀取將被中止 對於不可見的網頁,接收和推送 NFC 內容被暫停,並在網頁再次可見時恢復 Web NFC 示意圖(圖片來源: https://web-dev )
使用 Web NFC 的情境包括:
博物館中將裝置跟展覽的 Tag 接觸時,可以顯示有關訊息 商店可以做庫存管理 馬拉松比賽可以拿來讀取跑友的 RFID 怎麼使用 NDEFReader? 判斷是否支援,接著是取得權限 NDEFReader,只要叫用 scan() 和 write() 就會觸發權限的提示,也可以透過程式觸發。 1 2 3 4 5 6 7 8 9 10 11 if ("NDEFReader" in window ) { const nfcPermissionStatus = await navigator.permissions .query ({ name : "nfc" , }); if (nfcPermissionStatus.state === "granted" ) { } else { } }
new 一個 NDEFReader 然後就可以叫用 scan(),叫用後當 NFC 標籤接近時,NDEFReadingEvent 會觸發事件。reading 成功後會收到兩個屬性serialNumber: 表示設備的序列號(例如 00-11-22-33-44-55-66),如果沒有,則為空字符串。message: 表示存儲在 NFC 標籤中的 NDEF 消息。 寫入時的 option 也有兩種屬性overwrite: 不可覆寫要記得設定為 falserecords: 可以寫入多筆資訊 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 async function readTag ( ) { try { const ndef = new NDEFReader (); await ndef.scan (); ndef.addEventListener ("readingerror" , () => { log ("讀取錯誤" ); }); ndef.addEventListener ("reading" , ({ message, serialNumber } ) => { log (`> Serial Number: ${serialNumber} ` ); log (`> Records:(${message.records.length} )` ); }); } catch (error) { log ("錯誤" + error); } } async function writeTag ( ) { try { const ndef = new NDEFReader (); await ndef.write ("Hello world!" , { overwrite : false }); await ndef.write ({ records : [ { recordType : "url" , data : "https://w3c.github.io/web-nfc/" }, { recordType : "url" , data : "https://web.dev/nfc/" }, ], }); } catch (error) { log ("錯誤" + error); } }
收到的 message 可能含有多筆 records 這時候可以一筆一筆依照屬性取解析 1 2 3 4 5 6 7 8 9 10 11 12 for (const record of message.records ) { console .log ("Record type: " + record.recordType ); console .log ("MIME type: " + record.mediaType ); console .log ("Record id: " + record.id ); switch (record.recordType ) { case "text" : break ; case "url" : break ; default : } }
停止操作,透過 AbortController 中的 signal 當成參數送進去 scan()、write() 中可以隨時終止目前的動作。 1 2 3 4 5 6 7 8 9 10 11 12 13 const abortController = new AbortController ();abortController.signal .onabort = (event ) => {}; const ndef = new NDEFReader ();await ndef.scan ({ signal : abortController.signal });await ndef.write ("Hello world" , { signal : abortController.signal });function abortAction (event ) { abortController.abort (); } abortAction ();
FAQ:Web NFC 常見問題 Q1:所有手機都支援 Web NFC 嗎? A:目前主要支援 Android 版的 Chrome 89+ 。iOS 系統(Safari)雖然硬體支援 NFC,但目前尚未開放 Web NFC API 供網頁使用。iPhone 使用者通常仍需透過原生 App 來讀取 NFC 標籤。
Q2:Web NFC 可以讀取悠遊卡或信用卡的餘額嗎? A:不行。 Web NFC 目前僅支援 NDEF 格式的資料交換。悠遊卡、信用卡等通常使用更底層且加密的 ISO-DEP 或專有協議,基於安全考量,瀏覽器無法直接存取這些敏感的金融晶片資料。
Q3:如果我離開網頁(切換分頁),NFC 掃描還會繼續嗎? A:不會。為了保護使用者隱私並防止惡意網站背景掃描,Web NFC API 嚴格遵循 Page Visibility 規則。一旦網頁進入背景(不可見狀態)或螢幕鎖定,所有的讀取與寫入操作都會被瀏覽器自動暫停或終止。
更多相關文章 想提升 Web App 的留存率嗎?本篇 PWA 教學深入解析「新增至主畫面 (A2HS)」實作細節。我們將解析 Manifest 配置、Service Worker 註冊到 beforeinstallprompt 程式實戰。前 150 字直接回答 A2HS 定義,助您掌握 PWA 安裝提示的設計技巧與最佳實務。
想提升 PWA 品質嗎?本篇 PWA 稽核教學深入解析 Lighthouse 使用建議。我們將解析 FMP、TTI 等效能指標,並提供包含 Webpack 優化、離線瀏覽實作與跨瀏覽器相容性的 10+ 個檢查清單。前 150 字直接回答稽核核心價值,助您打造高品質 Web App。
想讓您的 Web App 像原生 App 一樣具備快速啟動功能嗎?本篇 PWA 捷徑教學深入解析 App Shortcuts 實作技巧。我們將分享如何透過 Manifest 配置快速啟動選單、應用場景與各平台支援限制。前 150 字直接回答 App Shortcuts 定義,助您打造更高效率的高品質 Web App。
想讓您的 Web App 擁有原生 App 般的流暢體驗嗎?本篇 PWA 架構教學深入探討 App Shell Model。我們將分享如何透過靜態資源快取與動態資料分離,提升感知效能與可靠性。前 150 字直接回答 App Shell 定義,助您打造秒開且離線可用的高品質 Web App。
想提升 Web App 在離線環境下的體驗嗎?本篇 PWA 背景同步教學深入掌握 Periodic Background Sync API 實作技巧。我們將解析註冊機制、權限檢查到監聽處理,助您實現定期自動更新。前 150 字直接回答背景同步定義,讓您的 Progressive Web App 在網路不穩時依然強大。
喜歡這篇文章,請幫忙拍拍手喔 🤣