โต้ตอบกับอุปกรณ์ NFC ใน Chrome สำหรับ Android

ตอนนี้สามารถอ่านและเขียนไปยังแท็ก NFC ได้แล้ว

François Beaufort
François Beaufort

Web NFC คืออะไร

NFC ย่อมาจาก Near Field Communications หรือเทคโนโลยีไร้สายระยะสั้น ทำงานที่ 13.56 MHz ซึ่งทำให้สามารถสื่อสารระหว่างอุปกรณ์ได้ในระยะไกล น้อยกว่า 10 ซม. และมีอัตราการส่งข้อมูลสูงสุด 424 กิโลบิต/วินาที

เว็บ NFC ช่วยให้เว็บไซต์อ่านและเขียนแท็ก NFC ได้เมื่อ ใกล้กับอุปกรณ์ของผู้ใช้ (โดยปกติคือ 5-10 ซม., 2-4 นิ้ว) ขอบเขตปัจจุบันจำกัดอยู่ที่รูปแบบ NFC Data Exchange (NDEF) ซึ่งเป็นขนาดเล็ก รูปแบบข้อความไบนารีที่ทำงานในรูปแบบแท็กต่างๆ

วันที่ โทรศัพท์กำลังเปิดใช้แท็ก NFC เพื่อแลกเปลี่ยนข้อมูล
แผนภาพการทำงานของ NFC

Use Case ที่แนะนำ

Web NFC ถูกจำกัดไว้สำหรับ NDEF เนื่องจากคุณสมบัติด้านความปลอดภัยของการอ่านและ การเขียนข้อมูล NDEF จะสามารถวัดปริมาณได้ง่ายกว่า การดำเนินการ I/O ระดับต่ำ (เช่น ISO-DEP, NFC-A/B, NFC-F), โหมดการสื่อสารแบบเพียร์ทูเพียร์ และการ์ดโฮสต์ ไม่รองรับการจำลอง (HCE)

ตัวอย่างเว็บไซต์ที่อาจใช้ Web NFC มีดังนี้

  • พิพิธภัณฑ์และแกลเลอรีศิลปะสามารถแสดงข้อมูลเพิ่มเติมเกี่ยวกับการจัดแสดงได้ เมื่อผู้ใช้แตะอุปกรณ์กับบัตร NFC ใกล้การจัดแสดง
  • เว็บไซต์การจัดการพื้นที่โฆษณาสามารถอ่านหรือเขียนข้อมูลลงในแท็ก NFC ใน เพื่ออัปเดตข้อมูลในเนื้อหา
  • เว็บไซต์การประชุมสามารถใช้ PIN เพื่อสแกนป้าย NFC ระหว่างจัดกิจกรรมและเพื่อให้มั่นใจว่า เพื่อป้องกันไม่ให้มีการเปลี่ยนแปลงข้อมูลที่เขียนไว้ในข้อความอีก
  • เว็บไซต์จะใช้อีเมลนี้เพื่อแชร์ข้อมูลลับเริ่มต้นที่จำเป็นสำหรับอุปกรณ์หรือบริการได้ สถานการณ์การจัดสรรและการทำให้ข้อมูลการกำหนดค่าใช้งานได้ในการดำเนินงาน
โทรศัพท์สแกนแท็ก NFC หลายแท็ก
ภาพการจัดการสินค้าคงคลัง NFC

สถานะปัจจุบัน

ขั้นตอน สถานะ
1. สร้างคำอธิบาย เสร็จสมบูรณ์
2. สร้างข้อกำหนดคร่าวๆ เบื้องต้น เสร็จสมบูรณ์
3. รวบรวมความคิดเห็นและ ทำซ้ำในการออกแบบ เสร็จสมบูรณ์
4. ช่วงทดลองใช้จากต้นทาง เสร็จสมบูรณ์
5. เปิดตัว เสร็จสมบูรณ์

ใช้ Web NFC

การตรวจหาฟีเจอร์

การตรวจหาฟีเจอร์สำหรับฮาร์ดแวร์แตกต่างจากที่คุณคุ้นเคย การมี NDEFReader บ่งบอกคุณว่าเบราว์เซอร์รองรับ Web NFC แต่ ไม่ว่าจะมีฮาร์ดแวร์ที่จำเป็น หรือไม่ก็ตาม โดยเฉพาะอย่างยิ่ง หากฮาร์ดแวร์ ไม่พบ สัญญาที่ส่งกลับโดยการเรียกบางรายการจะปฏิเสธ ฉันจะให้ รายละเอียดเมื่อฉันอธิบายNDEFReader

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

คำศัพท์

แท็ก NFC เป็นอุปกรณ์ NFC แบบแพสซีฟ ซึ่งหมายความว่าขับเคลื่อนโดยแม่เหล็ก เมื่อมีอุปกรณ์ NFC ที่ใช้งานอยู่ (เช่น โทรศัพท์) อยู่ในบริเวณใกล้เคียง แท็ก NFC มาในรูปแบบและแฟชั่นมากมาย เช่น สติกเกอร์ บัตรเครดิต ข้อมือติดแขน และ และอีกมากมาย

วันที่ รูปภาพแท็ก NFC แบบโปร่งใส
แท็ก NFC แบบโปร่งใส

ออบเจ็กต์ NDEFReader คือจุดแรกเข้าใน Web NFC ที่แสดงฟังก์ชันการทำงาน สำหรับเตรียมการอ่านและ/หรือการเขียนที่ดำเนินการสำเร็จเมื่อแท็ก NDEF อยู่ใกล้กัน NDEF ในภาษาNDEFReader ย่อมาจาก NFC Data Exchange รูปแบบ ซึ่งเป็นรูปแบบข้อความไบนารีขนาดเล็กที่ได้มาตรฐานตามฟอรัม NFC

ออบเจ็กต์ NDEFReader มีไว้เพื่อดำเนินการกับข้อความ NDEF ขาเข้าจากแท็ก NFC และสำหรับการเขียนข้อความ NDEF ไปยังแท็ก NFC ที่อยู่ภายในช่วง

แท็ก NFC ที่รองรับ NDEF เปรียบเสมือนโน้ตโพสต์อิต ทุกคนสามารถอ่านได้ และ เว้นแต่จะเป็นแบบอ่านอย่างเดียว ทุกคนสามารถเขียนได้ มี NDEF เดียว ข้อความที่สรุประเบียน NDEF อย่างน้อย 1 รายการ ระเบียน NDEF แต่ละรายการคือ โครงสร้างไบนารีที่มีเพย์โหลดข้อมูลและข้อมูลประเภทที่เกี่ยวข้อง เว็บ NFC สนับสนุนประเภทระเบียนมาตรฐานของฟอรัม NFC ดังต่อไปนี้: ว่างเปล่า, ข้อความ, URL, โปสเตอร์อัจฉริยะ, ประเภท MIME, URL ที่สมบูรณ์, ประเภทภายนอก, ไม่ทราบ และในเครื่อง ประเภท

วันที่ แผนภาพของข้อความ NDEF
แผนภาพของข้อความ NDEF

สแกนแท็ก NFC

หากต้องการสแกนแท็ก NFC ให้สร้างอินสแตนซ์ NDEFReader ใหม่ก่อน กำลังโทรหา scan() จะให้คำมั่นสัญญา ผู้ใช้อาจได้รับข้อความแจ้งหากไม่เคยมีการเข้าถึงมาก่อน ที่ได้รับ สัญญาจะได้รับการแก้ไขหากเป็นไปตามเงื่อนไขต่อไปนี้ทั้งหมด

  • มีการเรียกใช้เพื่อตอบสนองต่อท่าทางสัมผัสของผู้ใช้เท่านั้น เช่น ท่าทางสัมผัสการแตะ หรือ คลิกเมาส์
  • ผู้ใช้อนุญาตให้เว็บไซต์โต้ตอบกับอุปกรณ์ NFC
  • โทรศัพท์ของผู้ใช้รองรับ NFC
  • ผู้ใช้ได้เปิดใช้ NFC ในโทรศัพท์ของตน

เมื่อสัญญาสำเร็จ ข้อความ NDEF ขาเข้าจะพร้อมใช้งานภายในวันที่ สมัครรับข้อมูลเหตุการณ์ reading ผ่าน Listener เหตุการณ์ คุณควรสมัครรับอีเมลด้วย ไปยังเหตุการณ์ 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 จะเริ่มทำงาน ทั้งนี้ มีพร็อพเพอร์ตี้ 2 อย่างเฉพาะ ได้แก่

  • serialNumber แสดงหมายเลขซีเรียลของอุปกรณ์ (เช่น 00-11-22-33-44-55-66) หรือสตริงว่างหากไม่มีข้อมูล
  • message แสดงข้อความ NDEF ที่จัดเก็บไว้ในแท็ก NFC

หากต้องการอ่านเนื้อหาของข้อความ NDEF ให้วนซ้ำ message.records และ ประมวลผลสมาชิก data คนอย่างเหมาะสม โดยพิจารณาจากrecordTypeสมาชิก สมาชิก 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}.`);
});

หากต้องการเขียนระเบียน URL ไปยังแท็ก NFC ให้ส่งพจนานุกรมที่แสดงถึง NDEF ข้อความถึง write() ในตัวอย่างด้านล่าง ข้อความ NDEF คือพจนานุกรม ด้วยคีย์ records ค่าของรายการคืออาร์เรย์ของระเบียน ซึ่งในกรณีนี้คือ URL ระเบียนที่กำหนดเป็นออบเจ็กต์ที่มีการตั้งค่าคีย์ recordType เป็น "url" และ data ตั้งค่าเป็นสตริง URL

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 ที่ไม่ได้ตั้งใจให้เขียนทับ ให้ตั้งค่า พร็อพเพอร์ตี้ overwrite ไปยัง false ในตัวเลือกที่ส่งไปยัง write() ในกรณีดังกล่าว สัญญาที่ส่งกลับมาจะปฏิเสธหากข้อความ NDEF จัดเก็บไว้ในแท็ก NFC แล้ว

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 ได้

วันที่ ภาพหน้าจอของข้อความแจ้งเกี่ยวกับ NFC บนเว็บบนเว็บไซต์
ข้อความแจ้งผู้ใช้ NFC บนเว็บ

Web 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 จะ ถูกระงับ และจะกลับมาทำงานอีกครั้งเมื่อหน้าเว็บแสดงอีกครั้ง

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

ตำราอาหาร

นี่เป็นตัวอย่างโค้ดบางส่วนที่จะช่วยคุณเริ่มต้น

ตรวจสอบสิทธิ์

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 ได้อย่างง่ายดาย การดำเนินงาน ตัวอย่างด้านล่างแสดงวิธีผ่าน signal AbortController ผ่านตัวเลือกของ NDEFReader scan(), makeReadOnly(), เมธอด write() และล้มเลิกการทำงานของ 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 และอ่าน ข้อความใหม่ในแท็ก NFC อุปกรณ์จะหยุดสแกนหลังจากผ่านไป 3 วินาที

// 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 สามารถถอดรหัสได้ด้วย TextDecoder ที่สร้างอินสแตนซ์ บันทึกพร็อพเพอร์ตี้ encoding โปรดทราบว่าภาษาของระเบียนข้อความคือ พร้อมใช้งานผ่านพร็อพเพอร์ตี้ 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 โดยค่าเริ่มต้น และถือว่าเป็นภาษาของเอกสารปัจจุบัน แต่ สามารถระบุพร็อพเพอร์ตี้ทั้ง 2 รายการ (encoding และ lang) โดยใช้ไวยากรณ์แบบเต็มได้ สำหรับการสร้างระเบียน 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] });

อ่านและเขียนระเบียน URL

ใช้ TextDecoder เพื่อถอดรหัส data ของระเบียน

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

หากต้องการเขียนระเบียน URL ให้ส่งพจนานุกรมข้อความ NDEF ไปยัง NDEFReader write() วิธี ระเบียน URL ที่อยู่ในข้อความ NDEF มีการกำหนดเป็น มีการตั้งค่าคีย์ recordType เป็น "url" และตั้งค่าคีย์ data เป็น URL สตริง

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

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

อ่านและเขียนระเบียนประเภท MIME

พร็อพเพอร์ตี้ mediaType ของระเบียนประเภท MIME แสดงถึงประเภท MIME ของระเบียน เพย์โหลดระเบียน NDEF เพื่อให้ระบบถอดรหัส data ได้อย่างถูกต้อง เช่น ใช้ JSON.parse เพื่อถอดรหัสข้อความ JSON และเอลิเมนต์รูปภาพเพื่อถอดรหัสข้อมูลรูปภาพ

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() วิธี มีการกำหนดระเบียนประเภท MIME ที่อยู่ในข้อความ NDEF เป็นออบเจ็กต์ที่มีการตั้งค่าคีย์ recordType เป็น "mime" ซึ่งทำให้ตั้งค่าคีย์ mediaType เป็น ประเภท MIME จริงของเนื้อหา และชุดคีย์ data เป็นออบเจ็กต์ที่สามารถ เป็น ArrayBuffer หรือให้มุมมองสำหรับ ArrayBuffer (เช่น Uint8Array, DataView)

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

อ่านและเขียนระเบียน URL แบบสัมบูรณ์

ระเบียน URL แบบสัมบูรณ์ data สามารถถอดรหัสได้ด้วย TextDecoder แบบง่าย

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

หากต้องการเขียนระเบียน URL แบบสัมบูรณ์ ให้ส่งพจนานุกรมข้อความ NDEF ไปยัง เมธอด NDEFReader write() ระเบียน URL แบบสัมบูรณ์ที่มีอยู่ใน NDEF ข้อความ กำหนดเป็นออบเจ็กต์ที่มีการตั้งค่าคีย์ recordType เป็น "absolute-url" และคีย์ data ตั้งเป็นสตริง URL

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 เป็นรายการ ที่อยู่ในระเบียนโปสเตอร์อัจฉริยะ ซึ่งควรมีระเบียน URL ซึ่งเป็น ระเบียนข้อความสำหรับชื่อ ระเบียนประเภท 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() ของ ประกอบด้วยชื่อโดเมนขององค์กรที่ออกบัตร เครื่องหมายโคลอน และประเภท ชื่อที่มีความยาวอย่างน้อย 1 อักขระ เช่น "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 (เช่น Uint8Array, DataView)

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

การสนับสนุนเบราว์เซอร์

Web NFC พร้อมใช้งานบน Android ใน Chrome 89

เคล็ดลับสำหรับนักพัฒนาซอฟต์แวร์

ตอนที่เริ่มเล่น Web NFC ก็มีรายการที่หวังว่าจะรู้ได้ดังต่อไปนี้

  • Android จัดการแท็ก NFC ที่ระดับระบบปฏิบัติการก่อนที่ Web NFC จะทำงาน
  • คุณจะเห็นไอคอน NFC ใน material.io
  • ใช้ระเบียน 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 สุดเจ๋งต่อไปนี้

การสาธิตการ์ด NFC บนเว็บที่งาน Chrome Dev Summit 2019

ความคิดเห็น

กลุ่มชุมชน Web NFC และ ทีม Chrome อยากทราบความคิดเห็นและประสบการณ์การใช้งาน Web NFC ของคุณ

บอกเราเกี่ยวกับการออกแบบ API

มีบางอย่างเกี่ยวกับ API ที่ไม่ทำงานตามที่คาดไว้หรือไม่ หรือมี วิธีการหรือคุณสมบัติที่จำเป็นไม่ครบที่คุณต้องการนำไอเดียไปปฏิบัติ

แจ้งปัญหาเกี่ยวกับที่เก็บ GitHub ของ Web NFC หรือเพิ่มความเห็นของคุณไปที่ ปัญหาที่มีอยู่

รายงานปัญหาเกี่ยวกับการติดตั้งใช้งาน

คุณพบข้อบกพร่องในการติดตั้งใช้งาน Chrome ไหม หรือเป็นการติดตั้งใช้งาน แตกต่างจากข้อกำหนด

รายงานข้อบกพร่องที่ https://new.crbug.com ตรวจสอบว่าได้ใส่ ให้ละเอียดที่สุด บอกวิธีการง่ายๆ ในการจำลองข้อผิดพลาดซ้ำ ตั้งค่าคอมโพเนนต์เป็น Blink>NFC Glitch เหมาะสำหรับ แชร์ตัวอย่างผลงานที่ง่ายและรวดเร็ว

แสดงการสนับสนุน

คุณวางแผนที่จะใช้ Web NFC ไหม การสนับสนุนแบบสาธารณะของคุณจะช่วยทีม Chrome จัดลำดับความสำคัญของฟีเจอร์และแสดงให้ผู้ให้บริการเบราว์เซอร์รายอื่นเห็นความสำคัญของฟีเจอร์ สนับสนุนพวกเขา

ส่งทวีตไปยัง @ChromiumDev โดยใช้แฮชแท็ก #WebNFC และแจ้งให้เราทราบถึงตำแหน่งและวิธีที่คุณใช้งาน

ลิงก์ที่มีประโยชน์

กิตติกรรมประกาศ

ขอขอบคุณทีม Intel ที่ติดตั้งใช้งาน Web NFC Google Chrome จะขึ้นอยู่กับกลุ่มสมาชิกที่ทำงานร่วมกันในการย้าย Chromium ไปข้างหน้า คอมมิตเตอร์ของ Chromium บางคนอาจไม่ได้เป็น Googler และกลุ่มคนเหล่านี้ ผู้ร่วมให้คำบรรยายควรได้รับการยอมรับเป็นพิเศษ