เอกสารนี้อธิบายงาน NFC พื้นฐานที่คุณทำใน Android ซึ่งจะอธิบายวิธีส่งและรับข้อมูล NFC ในรูปแบบข้อความ NDEF รวมถึงอธิบาย API เฟรมเวิร์ก Android ที่รองรับฟีเจอร์เหล่านี้ ดูหัวข้อขั้นสูงเพิ่มเติม รวมถึงการพูดคุยเกี่ยวกับการทำงานกับข้อมูลที่ไม่ใช่ NDEF ได้ที่NFC ขั้นสูง
การอ่านข้อมูล NDEF จากแท็ก NFC จัดการโดยระบบการส่งแท็ก ซึ่งจะวิเคราะห์แท็ก NFC ที่ค้นพบ จัดหมวดหมู่ข้อมูลอย่างเหมาะสม และเริ่มแอปพลิเคชันที่สนใจข้อมูลที่จัดหมวดหมู่ แอปพลิเคชันที่จัดการแท็ก NFC ที่สแกนสามารถประกาศตัวกรอง Intent และขอจัดการข้อมูลได้
ระบบส่งแท็ก
อุปกรณ์ที่ใช้ระบบปฏิบัติการ Android มักจะมองหาแท็ก NFC เมื่อหน้าจอปลดล็อก เว้นแต่ว่า NFC จะปิดอยู่ในเมนูการตั้งค่าของอุปกรณ์ เมื่ออุปกรณ์ที่ทำงานด้วยระบบ Android พบแท็ก NFC ลักษณะการทำงานที่ต้องการคือให้กิจกรรมที่เหมาะสมที่สุดจัดการ Intent โดยไม่ต้องถามผู้ใช้ว่าจะใช้แอปพลิเคชันใด เนื่องจากอุปกรณ์สแกนแท็ก NFC ในระยะใกล้มาก จึงมีความเป็นไปได้ว่าการให้ผู้ใช้เลือกกิจกรรมด้วยตนเองจะทำให้ผู้ใช้ต้องย้ายอุปกรณ์ออกจากแท็กและทำให้การเชื่อมต่อขาด คุณควรพัฒนากิจกรรมให้จัดการเฉพาะแท็ก NFC ที่กิจกรรมของคุณสนใจเพื่อป้องกันไม่ให้เครื่องมือเลือกกิจกรรมปรากฏขึ้น
Android มีระบบการส่งแท็กพิเศษที่วิเคราะห์แท็ก NFC ที่สแกน แยกวิเคราะห์ และพยายามค้นหาแอปพลิเคชันที่สนใจข้อมูลที่สแกนเพื่อช่วยคุณบรรลุเป้าหมายนี้ โดยทำดังนี้
- แยกวิเคราะห์แท็ก NFC และหาประเภท MIME หรือ URI ที่ระบุเพย์โหลดข้อมูลในแท็ก
- การห่อหุ้มประเภท MIME หรือ URI และเพย์โหลดไว้ใน Intent ขั้นตอนแรกๆ 2 ขั้นตอนนี้อธิบายไว้ในวิธีแมปแท็ก NFC กับประเภท MIME และ URI
- เริ่มกิจกรรมตาม Intent โปรดดูรายละเอียดในหัวข้อวิธีส่งแท็ก NFC ไปยังแอปพลิเคชัน
วิธีจับคู่แท็ก NFC กับประเภท MIME และ URI
ก่อนเริ่มเขียนแอปพลิเคชัน NFC คุณควรทำความเข้าใจแท็ก NFC ประเภทต่างๆ, วิธีที่ระบบส่งแท็กแยกวิเคราะห์แท็ก NFC และการดำเนินการพิเศษที่ระบบส่งแท็กทำเมื่อตรวจพบข้อความ NDEF แท็ก NFC มีเทคโนโลยีหลากหลายรูปแบบและสามารถเขียนข้อมูลลงในแท็กได้หลายวิธี Android รองรับมาตรฐาน NDEF มากที่สุด ซึ่งกำหนดโดย NFC Forum
ข้อมูล NDEF จะรวมอยู่ในข้อความ (NdefMessage
) ที่มีระเบียน (NdefRecord
) อย่างน้อย 1 รายการ ระเบียน NDEF แต่ละรายการต้องอยู่ในรูปแบบที่ถูกต้องตามข้อกำหนดของประเภทระเบียนที่ต้องการสร้าง Android ยังรองรับแท็กประเภทอื่นๆ ที่ไม่มีข้อมูล NDEF ซึ่งคุณสามารถใช้งานโดยใช้คลาสในแพ็กเกจ android.nfc.tech
ดูข้อมูลเพิ่มเติมเกี่ยวกับเทคโนโลยีเหล่านี้ได้ที่หัวข้อ NFC ขั้นสูง การใช้แท็กประเภทอื่นๆ เหล่านี้เกี่ยวข้องกับการเขียนสแต็กโปรโตคอลของคุณเองเพื่อสื่อสารกับแท็ก เราจึงขอแนะนำให้ใช้ NDEF เมื่อเป็นไปได้เพื่อให้การพัฒนาง่ายขึ้นและรองรับอุปกรณ์ที่ทำงานด้วยระบบ Android ได้สูงสุด
หมายเหตุ: หากต้องการดาวน์โหลดข้อกำหนด NDEF ที่สมบูรณ์ ให้ไปที่เว็บไซต์เอกสารข้อกำหนดและการใช้งานของ NFC Forum และดูตัวอย่างวิธีสร้างระเบียน NDEF ได้ที่การสร้างระเบียน NDEF ประเภททั่วไป
ตอนนี้คุณทราบข้อมูลเบื้องต้นเกี่ยวกับแท็ก NFC แล้ว ส่วนต่อไปนี้จะอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่ Android จัดการแท็กรูปแบบ NDEF เมื่ออุปกรณ์ที่ทำงานด้วยระบบ Android สแกนแท็ก NFC ที่มีข้อมูลที่จัดรูปแบบ NDEF ระบบจะแยกวิเคราะห์ข้อความและพยายามหาประเภท MIME หรือ URI ที่ระบุของข้อมูล โดยระบบจะอ่าน NdefRecord
แรกใน NdefMessage
เพื่อกำหนดวิธีตีความข้อความ NDEF ทั้งหมด (ข้อความ NDEF อาจมีระเบียน NDEF หลายรายการ) ในข้อความ NDEF ที่มีรูปแบบถูกต้อง NdefRecord
แรกจะมีช่องต่อไปนี้
- TNF 3 บิต (รูปแบบชื่อประเภท)
- ระบุวิธีตีความฟิลด์ประเภทความยาวแปรผัน ค่าที่ใช้ได้มีอธิบายไว้ในตารางที่ 1
- ประเภทความยาวแปรผัน
- อธิบายประเภทของระเบียน หากใช้
TNF_WELL_KNOWN
ให้ใช้ช่องนี้เพื่อระบุคำจำกัดความของประเภทระเบียน (RTD) ค่า RTD ที่ถูกต้องจะอธิบายไว้ในตาราง 2 - รหัสที่มีความยาวแปรผัน
- ตัวระบุที่ไม่ซ้ำกันสำหรับระเบียน ฟิลด์นี้ไม่ค่อยได้ใช้ แต่หากต้องการระบุแท็กที่ไม่ซ้ำกัน คุณก็สร้างรหัสให้แท็กนั้นได้
- เพย์โหลดที่มีความยาวแปรผัน
- เพย์โหลดข้อมูลจริงที่คุณต้องการอ่านหรือเขียน ข้อความ NDEF อาจมีระเบียน NDEF หลายรายการ ดังนั้นอย่าคิดว่าเพย์โหลดทั้งหมดอยู่ในระเบียน NDEF รายการแรกของข้อความ NDEF
ระบบการส่งแท็กใช้ TNF และช่องประเภทเพื่อพยายามจับคู่ประเภท MIME หรือ URI กับข้อความ NDEF หากทําสําเร็จ ระบบจะรวมข้อมูลดังกล่าวไว้ใน Intent ACTION_NDEF_DISCOVERED
พร้อมกับเพย์โหลดจริง อย่างไรก็ตาม อาจมีกรณีที่ระบบส่งแท็กไม่สามารถระบุประเภทข้อมูลตามระเบียน NDEF รายการแรก กรณีนี้จะเกิดขึ้นเมื่อระบบจับคู่ข้อมูล NDEF กับประเภท MIME หรือ URI ไม่ได้ หรือเมื่อแท็ก NFC ไม่มีข้อมูล NDEF มาตั้งแต่ต้น ในกรณีเช่นนี้ ออบเจ็กต์ Tag
ที่มีข้อมูลเกี่ยวกับเทคโนโลยีของแท็กและเพย์โหลดจะรวมอยู่ใน Intent ACTION_TECH_DISCOVERED
แทน
ตารางที่ 1 อธิบายวิธีที่ระบบส่งแท็กแมป TNF และช่องประเภทกับประเภท MIME หรือ URI รวมถึงอธิบาย TNF ใดที่ไม่สามารถแมปกับประเภท MIME หรือ URI
ในกรณีเหล่านี้ ระบบการส่งแท็กจะใช้ ACTION_TECH_DISCOVERED
เช่น หากระบบส่งแท็กพบระเบียนประเภท TNF_ABSOLUTE_URI
ระบบจะแมปช่องประเภทที่มีความยาวแปรผันของระเบียนนั้นเป็น URI ระบบการส่งแท็กจะรวม URI นั้นไว้ในช่องข้อมูลของ Intent ACTION_NDEF_DISCOVERED
พร้อมกับข้อมูลอื่นๆ เกี่ยวกับแท็ก เช่น เพย์โหลด ในทางกลับกัน หากพบระเบียนประเภท TNF_UNKNOWN
ก็จะสร้าง Intent ที่รวมเทคโนโลยีของแท็กแทน
ตารางที่ 1 TNF ที่รองรับและการแมป
รูปแบบชื่อประเภท (TNF) | การแมป |
---|---|
TNF_ABSOLUTE_URI |
URI ตามช่องประเภท |
TNF_EMPTY |
ลดลงเป็น ACTION_TECH_DISCOVERED |
TNF_EXTERNAL_TYPE |
URI ตาม URN ในช่องประเภท ระบบจะเข้ารหัส URN ลงในช่องประเภท NDEF ในรูปแบบย่อ: <domain_name>:<service_name>
Android จะแมปข้อมูลนี้กับ URI ในรูปแบบต่อไปนี้
vnd.android.nfc://ext/<domain_name>:<service_name> |
TNF_MIME_MEDIA |
ประเภท MIME ตามช่องประเภท |
TNF_UNCHANGED |
ไม่ถูกต้องในระเบียนแรก จึงกลับไปใช้ ACTION_TECH_DISCOVERED |
TNF_UNKNOWN |
ลดลงเป็น ACTION_TECH_DISCOVERED |
TNF_WELL_KNOWN |
ประเภท MIME หรือ URI โดยขึ้นอยู่กับคําจํากัดความประเภทระเบียน (RTD) ที่คุณตั้งค่าไว้ในช่องประเภท ดูข้อมูลเพิ่มเติมเกี่ยวกับ RTD ที่ใช้ได้และการแมปได้ที่ตาราง 2 |
ตารางที่ 2 RTD ที่รองรับสําหรับ TNF_WELL_KNOWN และการแมป
คําจํากัดความของประเภทระเบียน (RTD) | การแมป |
---|---|
RTD_ALTERNATIVE_CARRIER |
ลดลงเป็น ACTION_TECH_DISCOVERED |
RTD_HANDOVER_CARRIER |
ลดลงเป็น ACTION_TECH_DISCOVERED |
RTD_HANDOVER_REQUEST |
ลดลงเป็น ACTION_TECH_DISCOVERED |
RTD_HANDOVER_SELECT |
ลดลงเป็น ACTION_TECH_DISCOVERED |
RTD_SMART_POSTER |
URI ตามการแยกวิเคราะห์เพย์โหลด |
RTD_TEXT |
ประเภท MIME ของ text/plain |
RTD_URI |
URI ตามเพย์โหลด |
วิธีส่งแท็ก NFC ไปยังแอปพลิเคชัน
เมื่อระบบส่งแท็กสร้าง Intent ที่รวมแท็ก NFC และข้อมูลระบุตัวตนของแท็กเสร็จแล้ว ก็จะส่ง Intent ไปยังแอปพลิเคชันที่เกี่ยวข้องซึ่งกรอง Intent นั้น หากมีแอปพลิเคชันมากกว่า 1 แอปที่จัดการ Intent ได้ ระบบจะแสดงเครื่องมือเลือกกิจกรรมเพื่อให้ผู้ใช้เลือกกิจกรรมได้ ระบบการส่งแท็กจะกําหนด Intent 3 รายการ ดังนี้ ซึ่งจะแสดงตามลําดับความสําคัญจากสูงสุดไปต่ำสุด
-
ACTION_NDEF_DISCOVERED
: Intent นี้ใช้เพื่อเริ่มกิจกรรมเมื่อสแกนแท็กที่มีเพย์โหลด NDEF และเป็นประเภทที่รู้จัก นี่เป็น Intent ที่มีลําดับความสําคัญสูงสุด และระบบการส่งแท็กจะพยายามเริ่มกิจกรรมด้วย Intent นี้ก่อน Intent อื่นๆ เมื่อเป็นไปได้หมายเหตุ: ตั้งแต่ Android 16 เป็นต้นไป การสแกนแท็ก NFC ที่เก็บลิงก์ URL (เช่น รูปแบบ URI คือ "htttps://" หรือ "http://") จะทริกเกอร์ Intent
ACTION_VIEW
แทน IntentACTION_NDEF_DISCOVERED
ACTION_TECH_DISCOVERED
: หากไม่มีกิจกรรมลงทะเบียนเพื่อจัดการกับ IntentACTION_NDEF_DISCOVERED
ระบบการส่งแท็กจะพยายามเริ่มแอปพลิเคชันด้วย Intent นี้ นอกจากนี้ ระบบยังจะเริ่มความตั้งใจนี้โดยตรง (โดยไม่ต้องเริ่มACTION_NDEF_DISCOVERED
ก่อน) หากแท็กที่สแกนมีข้อมูล NDEF ที่แมปกับประเภท MIME หรือ URI ไม่ได้ หรือหากแท็กไม่มีข้อมูล NDEF แต่ใช้เทคโนโลยีแท็กที่รู้จักACTION_TAG_DISCOVERED
: ระบบจะเริ่มความตั้งใจนี้หากไม่มีกิจกรรมใดจัดการความตั้งใจACTION_NDEF_DISCOVERED
หรือACTION_TECH_DISCOVERED
วิธีการทํางานพื้นฐานของระบบการส่งแท็กมีดังนี้
- ลองเริ่มกิจกรรมด้วย Intent ที่ระบบส่งแท็กสร้างขึ้นเมื่อแยกวิเคราะห์แท็ก NFC (
ACTION_NDEF_DISCOVERED
หรือACTION_TECH_DISCOVERED
) - หากไม่มีกิจกรรมที่กรองตาม Intent นั้น ให้ลองเริ่มกิจกรรมที่มี Intent ลำดับถัดไปที่มีลําดับความสําคัญต่ำที่สุด (
ACTION_TECH_DISCOVERED
หรือACTION_TAG_DISCOVERED
) จนกว่าแอปพลิเคชันจะกรอง Intent นั้น หรือจนกว่าระบบการส่งแท็กจะลองใช้ Intent ที่เป็นไปได้ทั้งหมด - หากไม่มีแอปพลิเคชันกรองสำหรับ Intent ใดเลย ให้ไม่ต้องดำเนินการใดๆ

เมื่อใดก็ตามที่เป็นไปได้ ให้ใช้ข้อความ NDEF และความตั้งใจ ACTION_NDEF_DISCOVERED
เนื่องจากมีความเฉพาะเจาะจงมากที่สุดในบรรดา 3 รายการ Intent นี้ช่วยให้คุณเริ่มแอปพลิเคชันในเวลาที่เหมาะสมกว่า Intent 2 รายการที่เหลือ ซึ่งจะช่วยให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีขึ้น
ขอสิทธิ์เข้าถึง NFC ในไฟล์ Manifest ของ Android
คุณต้องประกาศรายการต่อไปนี้ในไฟล์ AndroidManifest.xml
ก่อนจึงจะเข้าถึงฮาร์ดแวร์ NFC ของอุปกรณ์และจัดการ Intent ของ NFC ได้อย่างถูกต้อง
- องค์ประกอบ NFC
<uses-permission>
เพื่อเข้าถึงฮาร์ดแวร์ NFC<uses-permission android:name="android.permission.NFC" />
- เวอร์ชัน SDK ขั้นต่ำที่แอปพลิเคชันของคุณรองรับ API ระดับ 9 รองรับการส่งแท็กแบบจำกัดผ่าน
ACTION_TAG_DISCOVERED
เท่านั้น และให้สิทธิ์เข้าถึงข้อความ NDEF ผ่านEXTRA_NDEF_MESSAGES
เพิ่มเติมเท่านั้น คุณจะเข้าถึงพร็อพเพอร์ตี้แท็กหรือการดำเนินการ I/O อื่นๆ ไม่ได้ API ระดับ 10 รองรับเครื่องอ่าน/เครื่องเขียนอย่างครอบคลุม รวมถึงการพุช NDEF ในเบื้องหน้า และ API ระดับ 14 มีวิธีการที่สะดวกยิ่งขึ้นในการสร้างระเบียน NDEF<uses-sdk android:minSdkVersion="10"/>
- องค์ประกอบ
uses-feature
เพื่อให้แอปพลิเคชันของคุณปรากฏใน Google Play สำหรับอุปกรณ์ที่มีฮาร์ดแวร์ NFC เท่านั้น<uses-feature android:name="android.hardware.nfc" android:required="true" />
หากแอปพลิเคชันของคุณใช้ฟังก์ชัน NFC แต่ฟังก์ชันดังกล่าวไม่สำคัญต่อแอปพลิเคชัน คุณสามารถละเว้นองค์ประกอบ
uses-feature
และตรวจสอบความพร้อมใช้งานของ NFC ขณะรันไทม์โดยดูว่าgetDefaultAdapter()
เป็นnull
หรือไม่
ตัวกรองสำหรับ Intent ของ NFC
หากต้องการเริ่มแอปพลิเคชันเมื่อมีการสแกนแท็ก NFC ที่ต้องการจัดการ แอปพลิเคชันสามารถกรอง Intent ของ NFC รายการใดรายการหนึ่ง 2 รายการ หรือทั้ง 3 รายการในไฟล์ Manifest ของ Android อย่างไรก็ตาม คุณมักจะต้องกรองหา Intent ACTION_NDEF_DISCOVERED
เพื่อให้ควบคุมเวลาเริ่มต้นของแอปพลิเคชันได้มากที่สุด Intent ACTION_TECH_DISCOVERED
เป็น Intent สำรองสำหรับ ACTION_NDEF_DISCOVERED
เมื่อไม่มีแอปพลิเคชันกรองสำหรับ ACTION_NDEF_DISCOVERED
หรือเมื่อเพย์โหลดไม่ใช่ NDEF การกรองACTION_TAG_DISCOVERED
มักเป็นหมวดหมู่ที่กว้างเกินไปที่จะกรอง แอปพลิเคชันจำนวนมากจะกรอง ACTION_NDEF_DISCOVERED
หรือ ACTION_TECH_DISCOVERED
ก่อน ACTION_TAG_DISCOVERED
ดังนั้นแอปพลิเคชันของคุณจึงมีแนวโน้มต่ำที่จะเริ่มต้น ACTION_TAG_DISCOVERED
มีไว้เป็นทางเลือกสุดท้ายเท่านั้นสำหรับแอปพลิเคชันที่จะกรองหาในกรณีที่ไม่มีการติดตั้งแอปพลิเคชันอื่นเพื่อจัดการกับ Intent ACTION_NDEF_DISCOVERED
หรือ ACTION_TECH_DISCOVERED
เนื่องจากการติดตั้งใช้งานแท็ก NFC มีความหลากหลายและหลายครั้งอยู่นอกเหนือการควบคุมของคุณ การดำเนินการนี้จึงอาจไม่สามารถทำได้เสมอไป คุณจึงใช้ Intent อื่นๆ 2 รายการเป็นทางเลือกได้เมื่อจำเป็น เมื่อคุณควบคุมประเภทแท็กและข้อมูลที่เขียนได้ เราขอแนะนำให้คุณใช้ NDEF เพื่อจัดรูปแบบแท็ก ส่วนต่อไปนี้จะอธิบายวิธีกรองตามเจตนาแต่ละประเภท
ACTION_NDEF_DISCOVERED
หากต้องการกรอง Intent ACTION_NDEF_DISCOVERED
ให้ประกาศตัวกรอง Intent พร้อมกับประเภทข้อมูลที่ต้องการกรอง ตัวอย่างตัวกรองต่อไปนี้สําหรับACTION_NDEF_DISCOVERED
Intent ที่มีประเภท MIME เป็น text/plain
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /> </intent-filter>
ตัวอย่างต่อไปนี้จะกรอง URI ในรูปแบบของ https://developer.android.com/index.html
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
ACTION_TECH_DISCOVERED
หากกิจกรรมกรอง Intent ACTION_TECH_DISCOVERED
คุณต้องสร้างไฟล์ทรัพยากร XML ที่ระบุเทคโนโลยีที่กิจกรรมรองรับภายในชุด tech-list
ระบบจะถือว่ากิจกรรมของคุณตรงกันหากชุด tech-list
เป็นส่วนหนึ่งของเทคโนโลยีที่แท็กรองรับ ซึ่งคุณดูได้โดยเรียกใช้ getTechList()
ตัวอย่างเช่น หากแท็กที่สแกนรองรับ MifareClassic, NdefFormatable และ NfcA tech-list
ของคุณต้องระบุเทคโนโลยีทั้ง 3 รายการ 2 รายการ หรือ 1 รายการ (และไม่มีเทคโนโลยีอื่น) เพื่อให้ระบบจับคู่กิจกรรมได้
ตัวอย่างต่อไปนี้จะกำหนดเทคโนโลยีทั้งหมด คุณต้องนำบัตรที่แท็ก NFC ไม่รองรับออก บันทึกไฟล์นี้ (ตั้งชื่ออะไรก็ได้) ในโฟลเดอร์ <project-root>/res/xml
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.IsoDep</tech> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.NfcF</tech> <tech>android.nfc.tech.NfcV</tech> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> <tech>android.nfc.tech.MifareClassic</tech> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> </resources>
นอกจากนี้ คุณยังระบุชุด tech-list
ได้หลายชุด ระบบจะพิจารณาชุด tech-list
แต่ละชุดแยกกัน และถือว่ากิจกรรมของคุณตรงกันหากชุด tech-list
ชุดใดชุดหนึ่งเป็นชุดย่อยของเทคโนโลยีที่ getTechList()
แสดง ซึ่งระบุความหมายของ AND
และ OR
สำหรับเทคโนโลยีการจับคู่ ตัวอย่างต่อไปนี้จะจับคู่แท็กที่รองรับเทคโนโลยี NfcA และ Ndef หรือรองรับเทคโนโลยี NfcB และ Ndef
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> </resources>
ในไฟล์ AndroidManifest.xml
ให้ระบุไฟล์ทรัพยากรที่คุณเพิ่งสร้างขึ้นในองค์ประกอบ <meta-data>
ภายในองค์ประกอบ <activity>
ดังตัวอย่างต่อไปนี้
<activity> ... <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED"/> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> ... </activity>
ดูข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับเทคโนโลยีแท็กและ Intent ACTION_TECH_DISCOVERED
ได้ที่การทำงานกับเทคโนโลยีแท็กที่รองรับในเอกสาร NFC ขั้นสูง
ACTION_TAG_DISCOVERED
หากต้องการกรองหา ACTION_TAG_DISCOVERED
ให้ใช้ตัวกรอง Intent ต่อไปนี้
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
ACTION_VIEW
ตั้งแต่ Android 16 เป็นต้นไป การสแกนแท็ก NFC ที่เก็บลิงก์ URL จะทริกเกอร์ Intent ACTION_VIEW
หากต้องการกรองACTION_VIEW
ให้ดูthis
ใช้ Android app links
เพื่อเปิดแอปสำหรับ URL
รับข้อมูลจาก Intent
หากกิจกรรมเริ่มต้นขึ้นเนื่องจาก Intent ของ NFC คุณจะดูข้อมูลเกี่ยวกับแท็ก NFC ที่สแกนได้จาก Intent Intents อาจมีข้อมูลเพิ่มเติมต่อไปนี้โดยขึ้นอยู่กับแท็กที่สแกน
EXTRA_TAG
(ต้องระบุ): ออบเจ็กต์Tag
ที่แสดงแท็กที่สแกนEXTRA_NDEF_MESSAGES
(ไม่บังคับ): อาร์เรย์ของข้อความ NDEF ที่แยกวิเคราะห์จากแท็ก คุณต้องระบุค่าเพิ่มเติมนี้ในACTION_NDEF_DISCOVERED
IntentEXTRA_ID
(ไม่บังคับ): รหัสระดับล่างของแท็ก
หากต้องการรับข้อมูลเพิ่มเติมเหล่านี้ ให้ตรวจสอบว่ามีการเริ่มกิจกรรมด้วย Intent ของ NFC รายการใดรายการหนึ่งหรือไม่เพื่อให้แน่ใจว่ามีการสแกนแท็ก จากนั้นรับข้อมูลเพิ่มเติมจาก Intent ตัวอย่างต่อไปนี้จะตรวจสอบ Intent ACTION_NDEF_DISCOVERED
และรับข้อความ NDEF จาก Intent Extra
Kotlin
override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) ... if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) { intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMessages -> val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage } // Process the messages array. ... } } }
Java
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); ... if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMessages != null) { NdefMessage[] messages = new NdefMessage[rawMessages.length]; for (int i = 0; i < rawMessages.length; i++) { messages[i] = (NdefMessage) rawMessages[i]; } // Process the messages array. ... } } }
หรือจะรับออบเจ็กต์ Tag
จาก Intent ก็ได้ ซึ่งจะมีเพย์โหลดและให้คุณแจกแจงเทคโนโลยีของแท็กได้
Kotlin
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
สร้างระเบียน NDEF ประเภททั่วไป
ส่วนนี้จะอธิบายวิธีสร้างระเบียน NDEF ประเภททั่วไปเพื่อช่วยในการเขียนไปยังแท็ก NFC ตั้งแต่ Android 4.0 (API ระดับ 14) เป็นต้นไป วิธีการ createUri()
จะช่วยคุณสร้างระเบียน URI โดยอัตโนมัติ ตั้งแต่ Android 4.1 (API ระดับ 16) เป็นต้นไป createExternal()
และ createMime()
จะใช้เพื่อช่วยคุณสร้างระเบียน MIME และ NDEF ประเภทภายนอกได้ ใช้เมธอดตัวช่วยเหล่านี้ทุกครั้งที่เป็นไปได้เพื่อหลีกเลี่ยงข้อผิดพลาดเมื่อสร้างระเบียน NDEF ด้วยตนเอง
ส่วนนี้ยังอธิบายวิธีสร้างตัวกรอง Intent ที่เกี่ยวข้องสําหรับระเบียนด้วย ตัวอย่างระเบียน NDEF ทั้งหมดเหล่านี้ควรอยู่ในระเบียน NDEF แรกของข้อความ NDEF ที่คุณเขียนลงในแท็ก
TNF_ABSOLUTE_URI
หมายเหตุ: เราขอแนะนำให้ใช้ประเภท RTD_URI
แทน TNF_ABSOLUTE_URI
เนื่องจากมีประสิทธิภาพมากกว่า
คุณสร้างระเบียน TNF_ABSOLUTE_URI
NDEF ได้ดังนี้
Kotlin
val uriRecord = ByteArray(0).let { emptyByteArray -> NdefRecord( TNF_ABSOLUTE_URI, "https://developer.android.com/index.html".toByteArray(Charset.forName("US-ASCII")), emptyByteArray, emptyByteArray ) }
Java
NdefRecord uriRecord = new NdefRecord( NdefRecord.TNF_ABSOLUTE_URI , "https://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")), new byte[0], new byte[0]);
ตัวกรอง Intent สำหรับระเบียน NDEF ก่อนหน้าจะมีลักษณะดังนี้
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
TNF_MIME_MEDIA
คุณสร้างระเบียน NDEF TNF_MIME_MEDIA
ได้ดังนี้
การใช้เมธอด createMime()
Kotlin
val mimeRecord = NdefRecord.createMime( "application/vnd.com.example.android.beam", "Beam me up, Android".toByteArray(Charset.forName("US-ASCII")) )
Java
NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam", "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));
วิธีสร้าง NdefRecord
ด้วยตนเอง
Kotlin
val mimeRecord = Charset.forName("US-ASCII").let { usAscii -> NdefRecord( NdefRecord.TNF_MIME_MEDIA, "application/vnd.com.example.android.beam".toByteArray(usAscii), ByteArray(0), "Beam me up, Android!".toByteArray(usAscii) ) }
Java
NdefRecord mimeRecord = new NdefRecord( NdefRecord.TNF_MIME_MEDIA , "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")), new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
ตัวกรอง Intent สำหรับระเบียน NDEF ก่อนหน้าจะมีลักษณะดังนี้
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/vnd.com.example.android.beam" /> </intent-filter>
TNF_WELL_KNOWN ที่มี RTD_TEXT
คุณสร้างระเบียน NDEF TNF_WELL_KNOWN
ได้ดังนี้
Kotlin
fun createTextRecord(payload: String, locale: Locale, encodeInUtf8: Boolean): NdefRecord { val langBytes = locale.language.toByteArray(Charset.forName("US-ASCII")) val utfEncoding = if (encodeInUtf8) Charset.forName("UTF-8") else Charset.forName("UTF-16") val textBytes = payload.toByteArray(utfEncoding) val utfBit: Int = if (encodeInUtf8) 0 else 1 shl 7 val status = (utfBit + langBytes.size).toChar() val data = ByteArray(1 + langBytes.size + textBytes.size) data[0] = status.toByte() System.arraycopy(langBytes, 0, data, 1, langBytes.size) System.arraycopy(textBytes, 0, data, 1 + langBytes.size, textBytes.size) return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), data) }
Java
public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) { byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); byte[] textBytes = payload.getBytes(utfEncoding); int utfBit = encodeInUtf8 ? 0 : (1 << 7); char status = (char) (utfBit + langBytes.length); byte[] data = new byte[1 + langBytes.length + textBytes.length]; data[0] = (byte) status; System.arraycopy(langBytes, 0, data, 1, langBytes.length); System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); return record; }
ตัวกรอง Intent สำหรับระเบียน NDEF ก่อนหน้าจะมีลักษณะดังนี้
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter>
TNF_WELL_KNOWN ที่มี RTD_URI
คุณสร้างระเบียน NDEF TNF_WELL_KNOWN
ได้ดังนี้
การใช้เมธอด createUri(String)
Kotlin
val rtdUriRecord1 = NdefRecord.createUri("https://example.com")
Java
NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");
การใช้เมธอด createUri(Uri)
Kotlin
val rtdUriRecord2 = Uri.parse("https://example.com").let { uri -> NdefRecord.createUri(uri) }
Java
Uri uri = Uri.parse("https://example.com"); NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
วิธีสร้าง NdefRecord
ด้วยตนเอง
Kotlin
val uriField = "example.com".toByteArray(Charset.forName("US-ASCII")) val payload = ByteArray(uriField.size + 1) //add 1 for the URI Prefix payload [0] = 0x01 //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.size) //appends URI to payload val rtdUriRecord = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, ByteArray(0), payload)
Java
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII")); byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix payload[0] = 0x01; //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.length); //appends URI to payload NdefRecord rtdUriRecord = new NdefRecord( NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
ตัวกรอง Intent สำหรับระเบียน NDEF ก่อนหน้าจะมีลักษณะดังนี้
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="example.com" android:pathPrefix="" /> </intent-filter>
TNF_EXTERNAL_TYPE
คุณสร้างระเบียน TNF_EXTERNAL_TYPE
NDEF ได้ดังนี้
การใช้เมธอด createExternal()
Kotlin
var payload: ByteArray //assign to your data val domain = "com.example" //usually your app's package name val type = "externalType" val extRecord = NdefRecord.createExternal(domain, type, payload)
Java
byte[] payload; //assign to your data String domain = "com.example"; //usually your app's package name String type = "externalType"; NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);
วิธีสร้าง NdefRecord
ด้วยตนเอง
Kotlin
var payload: ByteArray ... val extRecord = NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".toByteArray(Charset.forName("US-ASCII")), ByteArray(0), payload )
Java
byte[] payload; ... NdefRecord extRecord = new NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".getBytes(Charset.forName("US-ASCII")), new byte[0], payload);
ตัวกรอง Intent สำหรับระเบียน NDEF ก่อนหน้าจะมีลักษณะดังนี้
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="vnd.android.nfc" android:host="ext" android:pathPrefix="/com.example:externalType"/> </intent-filter>
ใช้ TNF_EXTERNAL_TYPE
สำหรับการติดตั้งใช้งานแท็ก NFC ทั่วไปมากขึ้นเพื่อรองรับทั้งอุปกรณ์ที่ทำงานด้วยระบบ Android และอุปกรณ์ที่ทำงานด้วยระบบอื่นได้ดียิ่งขึ้น
หมายเหตุ: URN สำหรับ TNF_EXTERNAL_TYPE
มีรูปแบบมาตรฐานดังนี้
urn:nfc:ext:example.com:externalType
แต่ข้อกำหนด RTD ของ NFC Forum ระบุว่าต้องไม่ใส่ส่วน urn:nfc:ext:
ของ URN ไว้ในระเบียน NDEF คุณจึงต้องระบุเพียงโดเมน (example.com
ในตัวอย่าง) และประเภท (externalType
ในตัวอย่าง) โดยคั่นด้วยโคลอน
เมื่อส่ง TNF_EXTERNAL_TYPE
Android จะแปลง URN urn:nfc:ext:example.com:externalType
เป็น URI vnd.android.nfc://ext/example.com:externalType
ซึ่งเป็นค่าที่ตัวกรอง Intent ในตัวอย่างประกาศ
ระเบียนแอปพลิเคชัน Android
ระเบียนแอปพลิเคชัน Android (AAR) ซึ่งเปิดตัวใน Android 4.0 (API ระดับ 14) จะช่วยเพิ่มความมั่นใจได้ว่าแอปพลิเคชันจะเริ่มต้นเมื่อสแกนแท็ก NFC AAR มีชื่อแพ็กเกจของแอปพลิเคชันที่ฝังอยู่ในระเบียน NDEF คุณสามารถเพิ่ม AAR ลงในระเบียน NDEF ของข้อความ NDEF ใดก็ได้ เนื่องจาก Android จะค้นหา AAR ในข้อความ NDEF ทั้งหมด หากพบ AAR ระบบจะเริ่มแอปพลิเคชันตามชื่อแพ็กเกจภายใน AAR หากไม่มีแอปพลิเคชันดังกล่าวในอุปกรณ์ ระบบจะเปิด Google Play เพื่อดาวน์โหลดแอปพลิเคชัน
AAR จะมีประโยชน์ในกรณีที่คุณต้องการป้องกันไม่ให้แอปพลิเคชันอื่นๆ กรองหา Intent เดียวกันและอาจจัดการแท็กที่เฉพาะเจาะจงซึ่งคุณติดตั้งใช้งาน ระบบรองรับ AAR ที่ระดับแอปพลิเคชันเท่านั้นเนื่องจากข้อจํากัดของชื่อแพ็กเกจ และจะไม่รองรับที่ระดับกิจกรรมเหมือนกับการกรอง Intent หากต้องการจัดการ Intent ที่ระดับกิจกรรม ให้ใช้ตัวกรอง Intent
หากแท็กมี AAR ระบบจะส่งแท็กในลักษณะต่อไปนี้
- ลองเริ่มกิจกรรมโดยใช้ตัวกรอง Intent ตามปกติ หากกิจกรรมที่ตรงกับ Intent ตรงกับ AAR ด้วย ให้เริ่มกิจกรรม
- หากกิจกรรมที่กรอง Intent ไม่ตรงกับ AAR, หากมีกิจกรรมหลายรายการที่จัดการ Intent ได้ หรือหากไม่มีกิจกรรมใดจัดการ Intent ได้ ให้เริ่มแอปพลิเคชันที่ AAR ระบุ
- หากไม่มีแอปพลิเคชันใดที่เริ่มต้นด้วย AAR ให้ไปที่ Google Play เพื่อดาวน์โหลดแอปพลิเคชันตาม AAR
หมายเหตุ: คุณสามารถลบล้าง AAR และระบบการจัดเตรียม Intent ด้วยระบบการจัดเตรียมที่ทำงานอยู่เบื้องหน้า ซึ่งจะช่วยให้กิจกรรมที่ทำงานอยู่เบื้องหน้ามีลำดับความสำคัญเมื่อตรวจพบแท็ก NFC เมื่อใช้วิธีนี้ กิจกรรมต้องอยู่เบื้องหน้าเพื่อลบล้าง AAR และระบบการส่ง Intent
หากยังต้องการกรองแท็กที่สแกนซึ่งไม่มี AAR อยู่ คุณสามารถประกาศตัวกรอง Intent ได้ตามปกติ ซึ่งจะมีประโยชน์หากแอปพลิเคชันของคุณสนใจแท็กอื่นๆ ที่ไม่มี AAR เช่น คุณอาจต้องการรับประกันว่าแอปพลิเคชันจะจัดการแท็กที่เป็นกรรมสิทธิ์ซึ่งคุณติดตั้งใช้งาน รวมถึงแท็กทั่วไปที่บุคคลที่สามติดตั้งใช้งาน โปรดทราบว่า AAR ใช้ได้กับอุปกรณ์ Android 4.0 ขึ้นไปเท่านั้น ดังนั้นเมื่อติดตั้งใช้งานแท็ก คุณอาจต้องใช้ AAR ร่วมกับประเภท MIME/URI เพื่อรองรับอุปกรณ์ที่หลากหลายมากที่สุด นอกจากนี้ เมื่อติดตั้งใช้งานแท็ก NFC ให้พิจารณาว่าคุณต้องการเขียนข้อมูลในแท็ก NFC อย่างไรเพื่อให้รองรับอุปกรณ์ส่วนใหญ่ (อุปกรณ์ที่ใช้ Android และอุปกรณ์อื่นๆ) ซึ่งทำได้โดยการกำหนดประเภท MIME หรือ URI ที่ไม่ซ้ำกันเพื่อให้แอปพลิเคชันแยกแยะได้ง่ายขึ้น
Android มี API ที่ใช้งานง่ายในการสร้าง AAR
createApplicationRecord()
คุณเพียงต้องฝัง AAR ไว้ที่ใดก็ได้ใน NdefMessage
คุณไม่ต้องการใช้ระเบียนแรกของ NdefMessage
เว้นแต่ว่า AAR จะเป็นระเบียนเดียวใน NdefMessage
เนื่องจากระบบ Android จะตรวจสอบระเบียนแรกของ NdefMessage
เพื่อระบุประเภท MIME หรือ URI ของแท็ก ซึ่งจะใช้ในการสร้าง Intent สําหรับแอปพลิเคชันเพื่อกรอง โค้ดต่อไปนี้แสดงวิธีสร้าง AAR
Kotlin
val msg = NdefMessage( arrayOf( ..., NdefRecord.createApplicationRecord("com.example.android.beam") ) )
Java
NdefMessage msg = new NdefMessage( new NdefRecord[] { ..., NdefRecord.createApplicationRecord("com.example.android.beam")} ); )
รายการที่อนุญาตของแอปสำหรับการสแกนแท็ก NFC
ตั้งแต่ Android 16 เป็นต้นไป ผู้ใช้จะได้รับการแจ้งเตือนเมื่อแอปได้รับ Intent NFC รายการแรกเพื่อสแกนแท็ก NFC ผู้ใช้จะมีตัวเลือกในการไม่อนุญาตให้แอปสแกนหาแท็ก NFC อีกในการแจ้งเตือน
- แอปจะตรวจสอบได้ว่าผู้ใช้อนุญาตให้แอปสแกนแท็ก NFC หรือไม่โดยใช้
NfcAdapter.isTagIntentAllowed()
- แอปสามารถแจ้งให้ผู้ใช้อนุญาตการสแกนแท็ก NFC อีกครั้งได้โดยส่ง Intent
ACTION_CHANGE_TAG_INTENT_PREFERENCE
หมายเหตุ: รายการที่อนุญาตของแอปสแกนแท็ก NFC เข้าถึงได้ที่ Settings > Apps > Special app access > Launch via NFC