在 Android 版 Google Chrome 與 NFC 裝置互動

現在可以讀取及寫入 NFC 標記。

François Beaufort
François Beaufort

什麼是 Web NFC?

NFC 代表近距離無線通訊,這是一種短距離無線技術,頻率為 13.56 MHz,可讓裝置在距離不到 10 公分時進行通訊,傳輸速率最高可達 424 kbit/s。

Web NFC 可讓網站在 NFC 感應標籤靠近使用者裝置 (通常為 5 到 10 公分,即 2 到 4 英寸) 時讀取及寫入 NFC 感應標籤。目前的範圍僅限於 NFC 資料交換格式 (NDEF),這是一種輕量二進位訊息格式,可跨不同標記格式運作。

手機啟動 NFC 標記以交換資料
NFC 作業圖表

建議用途

Web NFC 受限於 NDEF,因為讀取和寫入 NDEF 資料的安全性屬性較容易量化。不支援低階 I/O 作業 (例如 ISO-DEP、NFC-A/B、NFC-F)、對等端通訊模式和主機式卡片模擬 (HCE)。

以下列舉一些可能會使用 Web NFC 的網站:

  • 當使用者將裝置輕觸展覽品附近的 NFC 卡時,博物館和藝廊就能顯示相關資訊。
  • 庫存管理網站可以讀取或寫入容器上的 NFC 標記資料,以更新其內容的資訊。
  • 會議網站可在活動期間使用這項功能掃描 NFC 徽章,並確保徽章已上鎖,以免日後變更其上寫的資訊。
  • 網站可以使用這項功能,分享裝置或服務佈建情境所需的初始密鑰,並在運作模式中部署設定資料。
手機掃描多個 NFC 標記
NFC 庫存管理示意圖

目前狀態

步驟 狀態
1. 建立說明 完成
2. 建立規格初稿 完成
3. 收集意見回饋並反覆改進設計 完成
4. 來源試用 完成
5. 啟動 完成

使用 Web NFC

特徵偵測

硬體功能偵測與您可能習慣的方式不同。如果出現 NDEFReader,就表示瀏覽器支援網路 NFC,但不知道該硬體是否存在必要硬體。特別是,如果缺少硬體,則某些呼叫傳回的承諾會遭到拒絕。我會在說明 NDEFReader 時提供詳細資訊。

if ('NDEFReader' in window) { /* Scan and write NFC tags */ }

術語

NFC 標記是被動式 NFC 裝置,也就是說,如果有效的 NFC 裝置 (例如手機) 就在附近,就能使用磁吸式感應功能。NFC 標籤有多種形式和款式,例如貼紙、信用卡、手腕等。

透明 NFC 標記的相片
透明 NFC 標記

NDEFReader 物件是 Web NFC 中的進入點,會在 NDEF 標記鄰近時,提供用於準備讀取和/或寫入動作的功能。NDEFReader 中的 NDEF 代表 NFC 資料交換格式,這種輕量的二進位訊息格式是由 NFC 論壇標準化。

NDEFReader 物件可處理來自 NFC 標記的傳入 NDEF 訊息,並將 NDEF 訊息寫入範圍內的 NFC 標記。

支援 NDEF 的 NFC 標籤就像便利貼,任何人都可以讀取,而且除非是唯讀,否則任何人都可以寫入。其中包含一個 NDEF 訊息,封裝一或多個 NDEF 記錄。每個 NDEF 記錄都是二進位結構,其中包含資料酬載和相關類型資訊。Web NFC 支援下列 NFC Forum 標準化記錄類型:空白、文字、網址、智慧海報、MIME 類型、絕對網址、外部類型、不明和本機類型。

NDEF 訊息圖表
NDEF 訊息圖表

掃描 NFC 標記

如要掃描 NFC 標籤,請先將新的 NDEFReader 物件例項化。呼叫 scan() 會傳回承諾。如果先前未授予存取權,系統可能會提示使用者。如果符合下列所有條件,承諾就會解析:

  • 只有在回應使用者手勢 (例如觸控手勢或滑鼠點選) 時,才會呼叫此方法。
  • 使用者已允許網站與 NFC 裝置互動。
  • 使用者的手機支援 NFC。
  • 使用者已在手機上啟用 NFC。

承諾解決後,您可以透過事件監聽器訂閱 reading 事件,接收傳入的 NDEF 訊息。您也應訂閱 readingerror 事件,以便在相容的 NFC 標記在附近時收到通知。

const ndef = new NDEFReader();
ndef.scan().then(() => {
  console.log("Scan started successfully.");
  ndef.onreadingerror = () => {
    console.log("Cannot read data from the NFC tag. Try another one?");
  };
  ndef.onreading = event => {
    console.log("NDEF message read.");
  };
}).catch(error => {
  console.log(`Error! Scan failed to start: ${error}.`);
});

當 NFC 標籤在附近時,系統會觸發 NDEFReadingEvent 事件。其中包含兩個專屬的屬性:

  • serialNumber 代表裝置的序號 (例如 00-11-22-33-44-55-66),如果沒有序號,則為空字串。
  • message 代表儲存在 NFC 標記中的 NDEF 訊息。

如要讀取 NDEF 訊息的內容,請循環 message.records,並根據 recordType 適當處理data 成員。data 成員會以 DataView 的形式公開,因為它可處理資料以 UTF-16 編碼的情況。

ndef.onreading = event => {
  const message = event.message;
  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":
        // TODO: Read text record with record data, lang, and encoding.
        break;
      case "url":
        // TODO: Read URL record with record data.
        break;
      default:
        // TODO: Handle other records with record data.
    }
  }
};

寫入 NFC 標記

如要寫入 NFC 標記,請先將新的 NDEFReader 物件例項化。呼叫 write() 會傳回承諾值。如果先前未授予存取權,系統可能會提示使用者。此時,NDEF 訊息便已「準備」,且若符合下列所有條件,就能解決問題:

  • 只有在回應使用者手勢 (例如觸控手勢或滑鼠點擊) 時才會呼叫。
  • 使用者已允許網站與 NFC 裝置互動。
  • 使用者的手機支援 NFC。
  • 使用者已在手機上啟用 NFC。
  • 使用者已輕觸 NFC 標籤,且已成功寫入 NDEF 訊息。

如要將文字寫入 NFC 標記,請將字串傳送至 write() 方法。

const ndef = new NDEFReader();
ndef.write(
  "Hello World"
).then(() => {
  console.log("Message written.");
}).catch(error => {
  console.log(`Write failed :-( try again: ${error}.`);
});

如要將網址記錄寫入 NFC 標記,請將代表 NDEF 訊息的字典傳送至 write()。在下列範例中,NDEF 訊息是包含 records 鍵的字典。其值為記錄陣列,在本例中,網址記錄定義為物件,其中 recordType 鍵設為 "url",而 data 鍵設為網址字串。

const ndef = new NDEFReader();
ndef.write({
  records: [{ recordType: "url", data: "https://w3c.github.io/web-nfc/" }]
}).then(() => {
  console.log("Message written.");
}).catch(error => {
  console.log(`Write failed :-( try again: ${error}.`);
});

您也可以將多筆記錄寫入 NFC 標記。

const ndef = new NDEFReader();
ndef.write({ records: [
    { recordType: "url", data: "https://w3c.github.io/web-nfc/" },
    { recordType: "url", data: "https://web.dev/nfc/" }
]}).then(() => {
  console.log("Message written.");
}).catch(error => {
  console.log(`Write failed :-( try again: ${error}.`);
});

如果 NFC 標記包含不應覆寫的 NDEF 訊息,請在傳遞至 write() 方法的選項中,將 overwrite 屬性設為 false。在這種情況下,如果 NFC 標籤中已儲存 NDEF 訊息,系統會傳回拒絕的承諾。

const ndef = new NDEFReader();
ndef.write("Writing data on an empty NFC tag is fun!", { overwrite: false })
.then(() => {
  console.log("Message written.");
}).catch(error => {
  console.log(`Write failed :-( try again: ${error}.`);
});

將 NFC 標記設為唯讀

為避免惡意使用者覆寫 NFC 標記的內容,您可以將 NFC 標記設為永久唯讀。這項操作是單向程序,無法復原。NFC 標籤一旦設為唯讀,就無法再寫入。

如要將 NFC 標籤設為唯讀,請先將新的 NDEFReader 物件例項化。呼叫 makeReadOnly() 會傳回承諾。如果先前未授予存取權,系統可能會提示使用者。如果滿足下列所有條件,承諾就會解析:

  • 只有在回應使用者手勢 (例如觸控手勢或滑鼠點選) 時,才會呼叫此方法。
  • 使用者已允許網站與 NFC 裝置互動。
  • 使用者的手機支援 NFC。
  • 使用者在手機上啟用 NFC。
  • 使用者已輕觸 NFC 標記,且 NFC 標記已成功設為唯讀。
const ndef = new NDEFReader();
ndef.makeReadOnly()
.then(() => {
  console.log("NFC tag has been made permanently read-only.");
}).catch(error => {
  console.log(`Operation failed: ${error}`);
});

以下說明如何在寫入 NFC 標記後永久設為唯讀。

const ndef = new NDEFReader();
try {
  await ndef.write("Hello world");
  console.log("Message written.");
  await ndef.makeReadOnly();
  console.log("NFC tag has been made permanently read-only after writing to it.");
} catch (error) {
  console.log(`Operation failed: ${error}`);
}

makeReadOnly() 可在 Android 版 Chrome 100 以上版本中使用,請確認是否支援以下功能:

if ("NDEFReader" in window && "makeReadOnly" in NDEFReader.prototype) {
  // makeReadOnly() is supported.
}

安全性和權限

Chrome 團隊根據「控制強大網路平台功能的存取權」一文中定義的核心原則,設計並實作 Web NFC,包括使用者控管、資訊公開和人體工學等原則。

由於 NFC 會擴大可能出現在惡意網站的資訊領域,因此 NFC 的可用性會受到限制,以提高使用者對 NFC 使用方式的瞭解與控制。

網站上的 Web NFC 提示螢幕截圖
Web NFC 使用者提示

網路 NFC 僅適用於頂層頁框和安全的瀏覽環境 (僅限 HTTPS)。來源必須先在處理使用者手勢 (例如按鈕點擊) 時要求 "nfc" 權限。如果先前未授予存取權,NDEFReader scan()write()makeReadOnly() 方法會觸發使用者提示。

  document.querySelector("#scanButton").onclick = async () => {
    const ndef = new NDEFReader();
    // Prompt user to allow website to interact with NFC devices.
    await ndef.scan();
    ndef.onreading = event => {
      // TODO: Handle incoming NDEF messages.
    };
  };

使用者啟動的權限提示以及在目標 NFC 標記上實際移動裝置時,兩者的結合,會反映其他檔案和裝置存取 API 中的選擇工具模式。

如要執行掃描或寫入作業,使用者必須用裝置觸碰 NFC 標籤,網頁才會顯示。瀏覽器會使用觸覺回饋來表示輕觸動作。如果螢幕關閉或裝置處於鎖定狀態,NFC 無線電將無法存取。針對未顯示的網頁,系統會暫時停用接收及推送 NFC 內容,並在網頁再次進入時恢復運作。

有了 Page Visibility API,您就能追蹤文件瀏覽權限變更的時間。

document.onvisibilitychange = event => {
  if (document.hidden) {
    // All NFC operations are automatically suspended when document is hidden.
  } else {
    // All NFC operations are resumed, if needed.
  }
};

食譜集

以下提供一些程式碼範例,協助您快速上手。

檢查權限

Permissions API 可讓您檢查是否已授予 "nfc" 權限。此範例說明如何在使用者先前授予存取權的情況下,不經使用者互動即可掃描 NFC 標籤,或在其他情況下顯示按鈕。請注意,相同的機制可用於寫入 NFC 標記,因為該標記實際上使用的權限相同。

const ndef = new NDEFReader();

async function startScanning() {
  await ndef.scan();
  ndef.onreading = event => {
    /* handle NDEF messages */
  };
}

const nfcPermissionStatus = await navigator.permissions.query({ name: "nfc" });
if (nfcPermissionStatus.state === "granted") {
  // NFC access was previously granted, so we can start NFC scanning now.
  startScanning();
} else {
  // Show a "scan" button.
  document.querySelector("#scanButton").style.display = "block";
  document.querySelector("#scanButton").onclick = event => {
    // Prompt user to allow UA to send and receive info when they tap NFC devices.
    startScanning();
  };
}

取消 NFC 作業

使用 AbortController 原始類別可輕鬆終止 NFC 作業。以下範例說明如何透過 NDEFReader scan()makeReadOnly()write() 方法的選項,傳遞 AbortControllersignal,並同時中止兩個 NFC 作業。

const abortController = new AbortController();
abortController.signal.onabort = event => {
  // All NFC operations have been aborted.
};

const ndef = new NDEFReader();
await ndef.scan({ signal: abortController.signal });

await ndef.write("Hello world", { signal: abortController.signal });
await ndef.makeReadOnly({ signal: abortController.signal });

document.querySelector("#abortButton").onclick = event => {
  abortController.abort();
};

寫入後讀取

使用 write()scan()AbortController 原始碼,即可在寫入訊息後讀取 NFC 標記。以下範例說明如何將文字訊息寫入 NFC 標記,並讀取 NFC 標記中的新訊息。會在三秒後停止掃描。

// Waiting for user to tap NFC tag to write to it...
const ndef = new NDEFReader();
await ndef.write("Hello world");
// Success! Message has been written.

// Now scanning for 3 seconds...
const abortController = new AbortController();
await ndef.scan({ signal: abortController.signal });
const message = await new Promise((resolve) => {
  ndef.onreading = (event) => resolve(event.message);
});
// Success! Message has been read.

await new Promise((r) => setTimeout(r, 3000));
abortController.abort();
// Scanning is now stopped.

讀取及寫入文字記錄

文字記錄 data 可透過使用記錄 encoding 屬性實例化的 TextDecoder 解碼。請注意,文字記錄的語言可透過其 lang 屬性取得。

function readTextRecord(record) {
  console.assert(record.recordType === "text");
  const textDecoder = new TextDecoder(record.encoding);
  console.log(`Text: ${textDecoder.decode(record.data)} (${record.lang})`);
}

如要寫入簡單的文字記錄,請將字串傳遞至 NDEFReader write() 方法。

const ndef = new NDEFReader();
await ndef.write("Hello World");

文字記錄預設為 UTF-8,並假設目前文件的語言,但兩個屬性 (encodinglang) 皆可使用完整語法指定,以便建立自訂 NDEF 記錄。

function a2utf16(string) {
  let result = new Uint16Array(string.length);
  for (let i = 0; i < string.length; i++) {
    result[i] = string.codePointAt(i);
  }
  return result;
}

const textRecord = {
  recordType: "text",
  lang: "fr",
  encoding: "utf-16",
  data: a2utf16("Bonjour, François !")
};

const ndef = new NDEFReader();
await ndef.write({ records: [textRecord] });

讀取及寫入網址記錄

使用 TextDecoder 解碼記錄的 data

function readUrlRecord(record) {
  console.assert(record.recordType === "url");
  const textDecoder = new TextDecoder();
  console.log(`URL: ${textDecoder.decode(record.data)}`);
}

如要寫入網址記錄,請將 NDEF 訊息字典傳送至 NDEFReader write() 方法。NDEF 訊息中包含的網址記錄定義為物件,其中 recordType 鍵設為 "url"data 鍵則設為網址字串。

const urlRecord = {
  recordType: "url",
  data:"https://w3c.github.io/web-nfc/"
};

const ndef = new NDEFReader();
await ndef.write({ records: [urlRecord] });

讀取及寫入 MIME 類型記錄

MIME 類型記錄的 mediaType 屬性代表 NDEF 記錄酬載的 MIME 類型,以便正確解碼 data。舉例來說,使用 JSON.parse 可將 JSON 文字解碼,並使用 Image 元素解碼圖片資料。

function readMimeRecord(record) {
  console.assert(record.recordType === "mime");
  if (record.mediaType === "application/json") {
    const textDecoder = new TextDecoder();
    console.log(`JSON: ${JSON.parse(decoder.decode(record.data))}`);
  }
  else if (record.mediaType.startsWith('image/')) {
    const blob = new Blob([record.data], { type: record.mediaType });
    const img = new Image();
    img.src = URL.createObjectURL(blob);
    document.body.appendChild(img);
  }
  else {
    // TODO: Handle other MIME types.
  }
}

如要寫入 MIME 類型記錄,請將 NDEF 訊息字典傳遞至 NDEFReader write() 方法。NDEF 訊息中包含的 MIME 類型記錄會定義為物件,其中 recordType 鍵設為 "mime"mediaType 鍵設為內容的實際 MIME 類型,而 data 鍵設為物件,該物件可以是 ArrayBuffer 或提供 ArrayBuffer 的檢視畫面 (例如 Uint8ArrayDataView)。

const encoder = new TextEncoder();
const data = {
  firstname: "François",
  lastname: "Beaufort"
};
const jsonRecord = {
  recordType: "mime",
  mediaType: "application/json",
  data: encoder.encode(JSON.stringify(data))
};

const imageRecord = {
  recordType: "mime",
  mediaType: "image/png",
  data: await (await fetch("icon1.png")).arrayBuffer()
};

const ndef = new NDEFReader();
await ndef.write({ records: [jsonRecord, imageRecord] });

讀取及寫入絕對網址記錄

絕對網址記錄 data 可透過簡單的 TextDecoder 解碼。

function readAbsoluteUrlRecord(record) {
  console.assert(record.recordType === "absolute-url");
  const textDecoder = new TextDecoder();
  console.log(`Absolute URL: ${textDecoder.decode(record.data)}`);
}

如要寫入絕對網址記錄,請將 NDEF 訊息字典傳遞至 NDEFReader write() 方法。NDEF 訊息中包含的絕對網址記錄會定義為物件,其中 recordType 鍵設為 "absolute-url",而 data 鍵則設為網址字串。

const absoluteUrlRecord = {
  recordType: "absolute-url",
  data:"https://w3c.github.io/web-nfc/"
};

const ndef = new NDEFReader();
await ndef.write({ records: [absoluteUrlRecord] });

讀取及寫入智慧海報記錄

智慧型海報記錄 (用於雜誌廣告、傳單、看板廣告等) 會將某些網路內容描述為 NDEF 記錄,其中包含 NDEF 訊息做為酬載。呼叫 record.toRecords() 即可將 data 轉換為智慧型海報記錄中包含的記錄清單。其中應包含網址記錄、標題文字記錄、圖片的 MIME 類型記錄,以及智慧型海報記錄的類型、動作和大小等部分自訂本機類型記錄,例如 ":t"":act"":s"

本地類型記錄僅在包含 NDEF 記錄的本地內容中才會是唯一的。當所含記錄的本機結構定義之外,以及儲存空間用量是硬性限制時,請使用這些類型代表的意義。在 Web NFC 中,本機類型記錄名稱一律以 : 開頭 (例如 ":t"":s"":act")。這可區分文字記錄和本機類型文字記錄。

function readSmartPosterRecord(smartPosterRecord) {
  console.assert(record.recordType === "smart-poster");
  let action, text, url;

  for (const record of smartPosterRecord.toRecords()) {
    if (record.recordType == "text") {
      const decoder = new TextDecoder(record.encoding);
      text = decoder.decode(record.data);
    } else if (record.recordType == "url") {
      const decoder = new TextDecoder();
      url = decoder.decode(record.data);
    } else if (record.recordType == ":act") {
      action = record.data.getUint8(0);
    } else {
      // TODO: Handle other type of records such as `:t`, `:s`.
    }
  }

  switch (action) {
    case 0:
      // Do the action
      break;
    case 1:
      // Save for later
      break;
    case 2:
      // Open for editing
      break;
  }
}

如要寫入智慧海報記錄,請將 NDEF 訊息傳遞至 NDEFReader write() 方法。NDEF 訊息中包含的智慧型海報記錄定義為一個物件,該物件的 recordType 鍵設為 "smart-poster",並將 data 鍵設為物件,代表智慧海報記錄中包含的 NDEF 訊息 (再次一次)。

const encoder = new TextEncoder();
const smartPosterRecord = {
  recordType: "smart-poster",
  data: {
    records: [
      {
        recordType: "url", // URL record for smart poster content
        data: "https://my.org/content/19911"
      },
      {
        recordType: "text", // title record for smart poster content
        data: "Funny dance"
      },
      {
        recordType: ":t", // type record, a local type to smart poster
        data: encoder.encode("image/gif") // MIME type of smart poster content
      },
      {
        recordType: ":s", // size record, a local type to smart poster
        data: new Uint32Array([4096]) // byte size of smart poster content
      },
      {
        recordType: ":act", // action record, a local type to smart poster
        // do the action, in this case open in the browser
        data: new Uint8Array([0])
      },
      {
        recordType: "mime", // icon record, a MIME type record
        mediaType: "image/png",
        data: await (await fetch("icon1.png")).arrayBuffer()
      },
      {
        recordType: "mime", // another icon record
        mediaType: "image/jpg",
        data: await (await fetch("icon2.jpg")).arrayBuffer()
      }
    ]
  }
};

const ndef = new NDEFReader();
await ndef.write({ records: [smartPosterRecord] });

讀取及寫入外部類型記錄

如要建立應用程式定義的記錄,請使用外部類型記錄。這些檔案可能會包含 NDEF 訊息,做為可透過 toRecords() 存取的酬載。其名稱包含發布機構的網域名稱、冒號和至少一個字元的型別名稱,例如 "example.com:foo"

function readExternalTypeRecord(externalTypeRecord) {
  for (const record of externalTypeRecord.toRecords()) {
    if (record.recordType == "text") {
      const decoder = new TextDecoder(record.encoding);
      console.log(`Text: ${textDecoder.decode(record.data)} (${record.lang})`);
    } else if (record.recordType == "url") {
      const decoder = new TextDecoder();
      console.log(`URL: ${decoder.decode(record.data)}`);
    } else {
      // TODO: Handle other type of records.
    }
  }
}

如要寫入外部類型記錄,請將 NDEF 訊息字典傳遞至 NDEFReader write() 方法。NDEF 訊息中包含的外部類型記錄定義為一個物件,該物件的 recordType 金鑰設定為外部類型名稱,並將 data 金鑰設為物件,代表外部類型記錄內含的 NDEF 訊息。請注意,data 鍵也可以是 ArrayBuffer,或提供 ArrayBuffer 的檢視畫面 (例如 Uint8ArrayDataView)。

const externalTypeRecord = {
  recordType: "example.game:a",
  data: {
    records: [
      {
        recordType: "url",
        data: "https://example.game/42"
      },
      {
        recordType: "text",
        data: "Game context given here"
      },
      {
        recordType: "mime",
        mediaType: "image/png",
        data: await (await fetch("image.png")).arrayBuffer()
      }
    ]
  }
};

const ndef = new NDEFReader();
ndef.write({ records: [externalTypeRecord] });

讀取及寫入空白記錄

空白記錄沒有酬載。

如要寫入空白記錄,請將 NDEF 訊息字典傳遞至 NDEFReader write() 方法。NDEF 訊息中包含的空白記錄定義為 recordType 鍵設為 "empty" 的物件。

const emptyRecord = {
  recordType: "empty"
};

const ndef = new NDEFReader();
await ndef.write({ records: [emptyRecord] });

瀏覽器支援

在 Android 上,Chrome 89 支援 Web NFC。

開發人員提示

以下是開始使用 Web NFC 時,我希望自己知道的事項:

  • 在 Web NFC 功能開始之前,Android 會在作業系統層級處理 NFC 標記。
  • 您可以在 material.io 上找到 NFC 圖示。
  • 需要時,可以使用 NDEF 記錄 id輕鬆識別記錄。
  • 未格式化的 NFC 標記 (支援 NDEF) 包含空值類型的單一記錄。
  • 編寫 Android 應用程式記錄很簡單,如下所示。
const encoder = new TextEncoder();
const aarRecord = {
  recordType: "android.com:pkg",
  data: encoder.encode("com.example.myapp")
};

const ndef = new NDEFReader();
await ndef.write({ records: [aarRecord] });

示範

請試用官方範例,並查看一些精彩的 Web NFC 示範:

2019 年 Chrome 開發人員高峰會的網路 NFC 卡片示範

意見回饋

Web NFC 社群群組和 Chrome 團隊很樂意聽取你對 Web NFC 的想法和體驗。

請說明 API 設計

API 是否有任何功能無法正常運作?或者,您是否缺少實作想法所需的方法或屬性?

您可以在 Web NFC GitHub 存放區上提出規格問題,或是將您的想法新增至現有問題。

回報導入問題

您發現 Chrome 實作錯誤嗎?還是實作方式與規格不同?

請前往 https://new.crbug.com 提交錯誤。請務必盡可能提供詳細資訊,提供重現錯誤的簡單操作說明,並將「元件」設為 Blink>NFCGlitch 非常適合用來快速輕鬆地提出重新提案。

顯示支援

您是否打算使用 Web NFC?公開支援服務可協助 Chrome 團隊優先開發特定功能,並讓其他瀏覽器廠商瞭解這些功能對這些功能的重要性。

使用主題標記 #WebNFC 發送推文給 @ChromiumDev,告訴我們你在何處使用這項功能,以及使用方式。

實用連結

特別銘謝

在此要向Intel 團隊致上萬分謝,感謝他們實作了 Web NFC。Google Chrome 需要有共同合作的社群成員,才能推動 Chromium 專案。並非每位 Chromium 提交者都是 Google 員工,這些貢獻者值得特別表揚!