ภาพรวม NFC ขั้นสูง

เอกสารนี้อธิบายถึงหัวข้อ NFC ขั้นสูง เช่น การทำงานกับเทคโนโลยีแท็กต่างๆ การเขียนไปยังแท็ก NFC และการจ่ายงานในเบื้องหน้า ซึ่งช่วยให้แอปพลิเคชันในเบื้องหน้าสามารถ จัดการ Intent แม้ว่าแอปพลิเคชันอื่นๆ จะกรองรายการเดียวกันก็ตาม

ทำงานกับเทคโนโลยีแท็กที่รองรับ

เมื่อทำงานกับแท็ก NFC และอุปกรณ์ที่ใช้ Android รูปแบบหลักที่คุณใช้อ่าน และเขียนข้อมูลบนแท็กคือ NDEF Android จะให้การสนับสนุนเมื่ออุปกรณ์สแกนแท็กที่มีข้อมูล NDEF ในการแยกวิเคราะห์ข้อความและนำส่งใน NdefMessage เมื่อ เท่าที่จะเป็นไปได้ อย่างไรก็ตาม มีบางกรณีเมื่อคุณสแกนแท็กที่ไม่มี ข้อมูล NDEF หรือเมื่อข้อมูล NDEF จับคู่กับประเภท MIME หรือ URI ไม่ได้ ในกรณีเหล่านี้ คุณต้องเปิดการสื่อสารโดยตรงกับแท็ก แล้วอ่านและเขียนลงในแท็กด้วย โปรโตคอลของคุณเอง (ในไบต์ดิบ) Android ให้การสนับสนุนทั่วไปสำหรับ Use Case เหล่านี้ด้วย android.nfc.tech ซึ่งอธิบายไว้ในตาราง 1 คุณสามารถ ใช้เมธอด getTechList() เพื่อระบุเทคโนโลยี แท็กรองรับและสร้าง TagTechnology ที่เกี่ยวข้อง ออบเจ็กต์ที่มีคลาสใดคลาสหนึ่งจัดเตรียมโดย android.nfc.tech

ตาราง 1 เทคโนโลยีแท็กที่รองรับ

ชั้น คำอธิบาย
TagTechnology อินเทอร์เฟซที่คลาสเทคโนโลยีแท็กทั้งหมดต้องติดตั้งใช้งาน
NfcA ให้สิทธิ์เข้าถึงคุณสมบัติ NFC-A (ISO 14443-3A) และการดำเนินการ I/O
NfcB ให้สิทธิ์เข้าถึงคุณสมบัติ NFC-B (ISO 14443-3B) และการดำเนินการ I/O
NfcF ให้สิทธิ์เข้าถึงพร็อพเพอร์ตี้ NFC-F (JIS 6319-4) และการดำเนินการ I/O
NfcV ให้สิทธิ์เข้าถึงคุณสมบัติ NFC-V (ISO 15693) และการดำเนินการ I/O
IsoDep ให้สิทธิ์เข้าถึงคุณสมบัติ ISO-DEP (ISO 14443-4) และการดำเนินการ I/O
Ndef ให้สิทธิ์เข้าถึงข้อมูลและการดำเนินการ NDEF ในแท็ก NFC ที่มีการจัดรูปแบบเป็น NDEF
NdefFormatable ระบุการดำเนินการของรูปแบบสำหรับแท็กที่อาจอยู่ในรูปแบบ NDEF ได้

อุปกรณ์ที่ใช้ Android ไม่จำเป็นต้องใช้เทคโนโลยีแท็กต่อไปนี้

ตาราง 2 เทคโนโลยีแท็กที่รองรับซึ่งไม่บังคับ

ชั้น คำอธิบาย
MifareClassic ให้สิทธิ์เข้าถึงพร็อพเพอร์ตี้ MIFARE Classic และการดำเนินการ I/O หากอุปกรณ์ Android นี้ รองรับ MIFARE
MifareUltralight ให้สิทธิ์เข้าถึงพร็อพเพอร์ตี้ MIFARE Ultralight และการดําเนินการ I/O หาก Android เครื่องนี้ อุปกรณ์รองรับ MIFARE

ทำงานกับเทคโนโลยีแท็กและความตั้งใจ ACTION_TECH_DISCOVERED

เมื่ออุปกรณ์สแกนแท็กที่มีข้อมูล NDEF แต่ไม่ได้แมปกับ MIME หรือ URI ระบบจ่ายแท็กพยายามเริ่มกิจกรรมด้วย ACTION_TECH_DISCOVERED Intent ระบบจะใช้ ACTION_TECH_DISCOVERED ด้วยเช่นกันเมื่อแท็ก ระบบจะสแกนข้อมูลที่ไม่ใช่ NDEF การมีทางเลือกสำรองนี้ช่วยให้คุณทำงานกับข้อมูลในแท็กได้ โดยตรง หากระบบจ่ายแท็กไม่สามารถแยกวิเคราะห์ให้คุณ ขั้นตอนพื้นฐานในการทำงานกับ เทคโนโลยีแท็กมีดังนี้

  1. ตัวกรองสำหรับ Intent ACTION_TECH_DISCOVERED ที่ระบุ เทคโนโลยีแท็กที่คุณต้องการจัดการ โปรดดูการกรองสำหรับ NFC Intent เพื่อดูข้อมูลเพิ่มเติม โดยทั่วไป ระบบการจ่ายแท็กจะพยายามเริ่มต้น Intent ACTION_TECH_DISCOVERED เมื่อมีข้อความ NDEF จะแมปกับประเภท MIME หรือ URI ไม่ได้ หรือหากแท็กที่สแกนไม่มีข้อมูล NDEF สำหรับ ข้อมูลเพิ่มเติมเกี่ยวกับวิธีกำหนด โปรดดูระบบการจ่ายแท็ก
  2. เมื่อแอปพลิเคชันได้รับ Intent ให้รับออบเจ็กต์ Tag จาก จุดประสงค์:

    Kotlin

    var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
    

    Java

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    
  3. รับอินสแตนซ์ของ TagTechnology โดยการเรียกใช้หนึ่งใน มีเมธอดจากโรงงาน get รายการของคลาสในแพ็กเกจ android.nfc.tech คุณสามารถ แจกแจงเทคโนโลยีที่รองรับของแท็กโดยการเรียกใช้ getTechList() ก่อนเรียกใช้เมธอด get จากโรงงาน เช่น หากต้องการรับอินสแตนซ์ ของ MifareUltralight จาก Tag ให้ทำดังนี้

    Kotlin

    MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
    

    Java

    MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
    

อ่านและเขียนไปยังแท็ก

การอ่านและการเขียนไปยังแท็ก NFC เกี่ยวข้องกับการรับแท็กจาก Intent และ การเปิดการสื่อสารด้วยแท็ก คุณต้องระบุสแต็กโปรโตคอลของคุณเองเพื่ออ่านและเขียนข้อมูล ลงในแท็ก อย่างไรก็ตาม โปรดทราบว่าคุณยังคงอ่านและเขียนข้อมูล NDEF ได้เมื่อทำงาน โดยตรงด้วยแท็ก ขึ้นอยู่กับคุณว่าต้องการจัดโครงสร้างของสิ่งต่างๆ อย่างไร ตัวอย่างต่อไปนี้แสดงวิธีทำงานกับแท็ก MIFARE Ultralight

Kotlin

package com.example.android.nfc
import android.nfc.Tag
import android.nfc.tech.MifareUltralight
import java.io.IOException
import java.nio.charset.Charset

class MifareUltralightTagTester {

    fun writeTag(tag: Tag, tagText: String) {
        MifareUltralight.get(tag)?.use { ultralight ->
            ultralight.connect()
            Charset.forName("US-ASCII").also { usAscii ->
                ultralight.writePage(4, "abcd".toByteArray(usAscii))
                ultralight.writePage(5, "efgh".toByteArray(usAscii))
                ultralight.writePage(6, "ijkl".toByteArray(usAscii))
                ultralight.writePage(7, "mnop".toByteArray(usAscii))
            }
        }
    }

    fun readTag(tag: Tag): String? {
        return MifareUltralight.get(tag)?.use { mifare ->
            mifare.connect()
            val payload = mifare.readPages(4)
            String(payload, Charset.forName("US-ASCII"))
        }
    }
}

Java

package com.example.android.nfc;

import android.nfc.Tag;
import android.nfc.tech.MifareUltralight;
import android.util.Log;
import java.io.IOException;
import java.nio.charset.Charset;

public class MifareUltralightTagTester {

    private static final String TAG = MifareUltralightTagTester.class.getSimpleName();

    public void writeTag(Tag tag, String tagText) {
        MifareUltralight ultralight = MifareUltralight.get(tag);
        try {
            ultralight.connect();
            ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII")));
            ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII")));
            ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII")));
            ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII")));
        } catch (IOException e) {
            Log.e(TAG, "IOException while writing MifareUltralight...", e);
        } finally {
            try {
                ultralight.close();
            } catch (IOException e) {
                Log.e(TAG, "IOException while closing MifareUltralight...", e);
            }
        }
    }

    public String readTag(Tag tag) {
        MifareUltralight mifare = MifareUltralight.get(tag);
        try {
            mifare.connect();
            byte[] payload = mifare.readPages(4);
            return new String(payload, Charset.forName("US-ASCII"));
        } catch (IOException e) {
            Log.e(TAG, "IOException while reading MifareUltralight message...", e);
        } finally {
            if (mifare != null) {
               try {
                   mifare.close();
               }
               catch (IOException e) {
                   Log.e(TAG, "Error closing tag...", e);
               }
            }
        }
        return null;
    }
}

ใช้ระบบการจ่ายงานที่ทำงานอยู่เบื้องหน้า

ระบบการจ่ายงานที่ทำงานอยู่เบื้องหน้าอนุญาตให้กิจกรรมสกัดกั้นความตั้งใจและการอ้างสิทธิ์ได้ ลำดับความสำคัญเหนือกิจกรรมอื่นๆ ที่จัดการความตั้งใจเดียวกัน การใช้ระบบนี้เกี่ยวข้องกับ สร้างโครงสร้างข้อมูลสองสามแบบเพื่อให้ระบบ Android สามารถส่ง กับแอปพลิเคชันของคุณ วิธีเปิดใช้ระบบการจ่ายงานที่ทำงานอยู่เบื้องหน้า

  1. เพิ่มโค้ดต่อไปนี้ในเมธอด onCreate() ของกิจกรรม
    1. สร้างออบเจ็กต์ PendingIntent ที่เปลี่ยนแปลงได้เพื่อให้ระบบ Android ป้อนข้อมูลได้ พร้อมรายละเอียดของแท็กเมื่อสแกน

      Kotlin

      val intent = Intent(this, javaClass).apply {
          addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
      }
      var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent,
              PendingIntent.FLAG_MUTABLE)
      

      Java

      PendingIntent pendingIntent = PendingIntent.getActivity(
          this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
          PendingIntent.FLAG_MUTABLE);
      
    2. ประกาศตัวกรอง Intent เพื่อจัดการ Intent ที่คุณต้องการสกัดกั้น เบื้องหน้า ระบบการจ่ายงานจะตรวจสอบตัวกรอง Intent ที่ระบุกับ Intent ที่ได้รับเมื่อ อุปกรณ์จะสแกนแท็ก หากตรงกัน แอปพลิเคชันของคุณจะจัดการ Intent หากใช่ ไม่ตรงกัน ระบบการจ่ายงานที่ทำงานอยู่เบื้องหน้าจะกลับไปใช้ระบบการจ่ายงาน Intent แทน การระบุอาร์เรย์ null ของตัวกรอง Intent และตัวกรองเทคโนโลยีจะระบุ ที่คุณต้องการกรองสำหรับแท็กทั้งหมดที่สำรองเป็น TAG_DISCOVERED Intent ข้อมูลโค้ดด้านล่างจะรองรับ MIME ทุกประเภทสำหรับ NDEF_DISCOVERED คุณ ควรจะจัดการเฉพาะ ส่วนที่คุณต้องการเท่านั้น

      Kotlin

      val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {
          try {
              addDataType("*/*")    /* Handles all MIME based dispatches.
                                       You should specify only the ones that you need. */
          } catch (e: IntentFilter.MalformedMimeTypeException) {
              throw RuntimeException("fail", e)
          }
      }
      
      intentFiltersArray = arrayOf(ndef)
      

      Java

      IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
          try {
              ndef.addDataType("*/*");    /* Handles all MIME based dispatches.
                                             You should specify only the ones that you need. */
          }
          catch (MalformedMimeTypeException e) {
              throw new RuntimeException("fail", e);
          }
         intentFiltersArray = new IntentFilter[] {ndef, };
      
    3. ตั้งค่าอาร์เรย์ของเทคโนโลยีแท็กที่แอปพลิเคชันของคุณต้องการจัดการ เรียกใช้ Object.class.getName()วิธีการรับข้อมูลคลาสของเทคโนโลยี ต้องการสนับสนุน

      Kotlin

      techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
      

      Java

      techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
      
  2. ลบล้าง Callback ของวงจรกิจกรรมต่อไปนี้ และเพิ่มตรรกะเพื่อเปิดใช้และปิดใช้ การจ่ายงานเบื้องหน้าเมื่อกิจกรรมหายไป (onPause()) และจะโฟกัสได้อีกครั้ง (onResume()) ต้องเรียก enableForegroundDispatch() จาก เทรดหลักและเฉพาะเมื่อกิจกรรมอยู่เบื้องหน้า (การเรียกใช้ใน onResume() รับประกันการดำเนินการนี้) คุณต้องใช้ Callback onNewIntent ในการประมวลผลข้อมูลจาก NFC ที่สแกนด้วย แท็ก
  3. Kotlin

    public override fun onPause() {
        super.onPause()
        adapter.disableForegroundDispatch(this)
    }
    
    public override fun onResume() {
        super.onResume()
        adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)
    }
    
    public override fun onNewIntent(intent: Intent) {
        val tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
        // do something with tagFromIntent
    }
    

    Java

    public void onPause() {
        super.onPause();
        adapter.disableForegroundDispatch(this);
    }
    
    public void onResume() {
        super.onResume();
        adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
    }
    
    public void onNewIntent(Intent intent) {
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        // do something with tagFromIntent
    }