Bergabunglah bersama kami di ⁠#Android11: The Beta Launch Show pada tanggal 3 Juni!

Ringkasan NFC lanjutan

Dokumen ini menjelaskan topik NFC lanjutan, seperti penggunaan berbagai teknologi tag, penulisan ke tag NFC, dan pengiriman latar depan, yang memungkinkan aplikasi di latar depan menangani intent, meski aplikasi lain memfilter intent yang sama.

Menggunakan teknologi tag yang didukung

Saat menggunakan tag NFC dan perangkat Android, format utama yang Anda gunakan untuk membaca dan menulis data pada tag adalah NDEF. Saat perangkat memindai tag dengan data NDEF, Android memberikan dukungan penguraian pesan dan pengirimannya dalam NdefMessage jika memungkinkan. Namun, ada kalanya Anda memindai tag yang tidak berisi data NDEF atau saat data NDEF tidak dapat dipetakan ke jenis MIME atau URI. Dalam kasus ini, Anda harus membuka komunikasi secara langsung dengan tag serta membaca dan menulis ke tag menggunakan protokol Anda sendiri (dalam byte raw). Android memberikan dukungan umum untuk kasus penggunaan ini dengan paket android.nfc.tech, yang dijelaskan dalam Tabel 1. Anda dapat menggunakan metode getTechList() untuk menentukan teknologi yang didukung oleh tag dan membuat objek TagTechnology yang sesuai dengan salah satu class yang diberikan oleh android.nfc.tech.

Tabel 1. Teknologi tag yang didukung

Class Deskripsi
TagTechnology Antarmuka yang harus diterapkan oleh semua class teknologi tag.
NfcA Menyediakan akses ke properti NFC-A (ISO 14443-3A) dan operasi I/O.
NfcB Menyediakan akses ke properti NFC-B (ISO 14443-3B) dan operasi I/O.
NfcF Menyediakan akses ke properti NFC-F (JIS 6319-4) dan operasi I/O.
NfcV Menyediakan akses ke properti NFC-V (ISO 15693) dan operasi I/O.
IsoDep Menyediakan akses ke properti ISO-DEP (ISO 14443-4) dan operasi I/O.
Ndef Menyediakan akses ke data NDEF dan operasi pada tag NFC yang telah diformat sebagai NDEF.
NdefFormatable Menyediakan operasi format untuk tag yang dapat diformat NDEF.

Teknologi tag berikut tidak harus didukung oleh perangkat Android.

Tabel 2. Teknologi tag opsional yang didukung.

Class Deskripsi
MifareClassic Memberikan akses ke properti MIFARE Classic dan operasi I/O, jika perangkat Android ini mendukung MIFARE.
MifareUltralight Memberikan akses ke properti MIFARE Ultralight dan operasi I/O, jika perangkat Android ini mendukung MIFARE.

Menggunakan teknologi tag dan intent ACTION_TECH_DISCOVERED

Saat perangkat memindai tag yang berisi data NDEF, tetapi tidak dapat dipetakan ke MIME atau URI, sistem pengiriman tag akan mencoba memulai aktivitas dengan intent ACTION_TECH_DISCOVERED. ACTION_TECH_DISCOVERED juga digunakan saat tag dengan data non-NDEF dipindai. Dengan adanya fallback ini, Anda dapat langsung menggunakan data pada tag jika sistem pengiriman tag tidak dapat menguraikannya untuk Anda. Langkah-langkah dasar saat menggunakan teknologi tag adalah sebagai berikut:

  1. Filter intent ACTION_TECH_DISCOVERED yang menentukan teknologi tag yang ingin Anda tangani. Lihat Memfilter intent NFC untuk mengetahui informasi selengkapnya. Umumnya, sistem pengiriman tag akan mencoba memulai intent ACTION_TECH_DISCOVERED saat pesan NDEF tidak dapat dipetakan ke jenis MIME atau URI, atau jika tag yang dipindai tidak berisi data NDEF. Untuk mengetahui informasi selengkapnya tentang cara menentukannya, lihat Sistem Pengiriman Tag.
  2. Saat aplikasi menerima intent, dapatkan objek Tag dari intent:

    Kotlin

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

    Java

        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        
  3. Dapatkan instance TagTechnology, dengan memanggil salah satu metode factory get dari class dalam paket android.nfc.tech. Anda dapat menghitung teknologi tag yang didukung dengan memanggil getTechList() sebelum memanggil metode factory get. Misalnya, untuk mendapatkan instance MifareUltralight dari Tag, lakukan hal-hal berikut:

    Kotlin

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

    Java

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

Membaca dan menulis ke tag

Membaca dan menulis ke tag NFC berarti mendapatkan tag dari intent dan membuka komunikasi dengan tag. Anda harus menentukan stack protokol Anda sendiri untuk membaca dan menulis data pada tag. Namun, perlu diperhatikan bahwa Anda tetap dapat membaca dan menulis data NDEF saat menggunakan tag secara langsung. Anda memiliki kebebasan untuk menyusun objek. Contoh berikut menunjukkan cara menggunakan tag 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;
        }
    }
    

Menggunakan sistem pengiriman latar depan

Sistem pengiriman layar depan memungkinkan aktivitas mengintersepsi intent dan mendapatkan prioritas di atas aktivitas lain yang menangani intent yang sama. Menggunakan sistem ini melibatkan pembuatan beberapa struktur data agar sistem Android dapat mengirim intent yang sesuai ke aplikasi Anda. Untuk mengaktifkan sistem pengiriman latar depan:

  1. Tambahkan kode berikut dalam metode onCreate() dari aktivitas Anda:
    1. Buat objek PendingIntent agar sistem Android dapat mengisinya dengan rincian tag saat dipindai.

      Kotlin

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

      Java

          PendingIntent pendingIntent = PendingIntent.getActivity(
              this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
          
    2. Deklarasikan filter intent untuk menangani intent yang ingin diintersepsi. Sistem pengiriman latar depan memeriksa filter intent yang ditentukan dengan intent yang diterima saat perangkat memindai tag. Jika sesuai, aplikasi Anda akan menangani intent. Jika tidak sesuai, sistem pengiriman latar belakang akan melakukan fallback ke sistem pengiriman intent. Menentukan array null filter intent dan filter teknologi, menentukan bahwa Anda ingin memfilter semua tag yang melakukan fallback ke intent TAG_DISCOVERED. Cuplikan kode di bawah ini menangani semua jenis MIME untuk NDEF_DISCOVERED. Anda hanya perlu menangani apa yang Anda butuhkan.

      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. Siapkan array teknologi tag yang ingin ditangani oleh aplikasi Anda. Panggil metode Object.class.getName() untuk mendapatkan class teknologi yang ingin didukung.

      Kotlin

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

      Java

          techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
          
  2. Ganti callback siklus hidup aktivitas berikut dan tambahkan logika untuk mengaktifkan dan menonaktifkan pengiriman latar depan saat aktivitas kehilangan (onPause()) dan mendapatkan fokus (onResume()) kembali. enableForegroundDispatch() harus dipanggil dari thread utama dan hanya saat aktivitas berada di latar depan (memanggil onResume() dapat menjamin hal ini). Anda juga perlu menerapkan callback onNewIntent untuk memproses data dari tag NFC yang sudah dipindai.
  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
        }
        

Lihat contoh ForegroundDispatch dari Demo API untuk contoh lengkapnya.