Dasar-dasar NFC

Dokumen ini menjelaskan tugas-tugas NFC dasar yang Anda jalankan di Android. Dokumen ini menjelaskan cara mengirim dan menerima data NFC dalam bentuk pesan NDEF serta menjelaskan API framework Android yang mendukung fitur ini. Untuk topik lanjutan lainnya, termasuk pembahasan tentang cara menggunakan data non-NDEF, lihat NFC Lanjutan.

Ada dua kasus penggunaan utama saat menggunakan data NDEF dan Android:

  • Membaca data NDEF dari tag NFC
  • Melakukan beaming pesan NDEF dari satu perangkat ke perangkat lainnya dengan Android Beam™

Pembacaan data NDEF dari tag NFC ditangani dengan sistem pengiriman tag, yang menganalisis tag NFC yang ditemukan, mengelompokkan data dengan tepat, dan memulai aplikasi yang berkaitan dengan data yang dikategorikan. Aplikasi yang ingin menangani tag NFC yang dipindai dapat mendeklarasikan filter intent dan meminta untuk menangani data tersebut.

Dengan fitur Android Beam™, perangkat dapat mengirim pesan NDEF ke perangkat lain dengan mengetukkan perangkat satu dengan yang lain secara bersamaan. Interaksi ini lebih memudahkan pengiriman data daripada teknologi nirkabel lainnya seperti Bluetooth, karena dengan NFC, penemuan atau penyambungan perangkat secara manual tidak diperlukan. Koneksi dimulai secara otomatis saat dua perangkat berada dalam jangkauan. Android Beam tersedia melalui serangkaian API NFC, sehingga aplikasi apa pun dapat mengirim informasi antar-perangkat. Misalnya, aplikasi Kontak, Browser, dan YouTube menggunakan Android Beam untuk berbagi kontak, halaman web, serta video dengan perangkat lain.

Sistem pengiriman tag

Perangkat Android biasanya mencari tag NFC saat layar tidak terkunci, kecuali jika NFC dinonaktifkan di menu Setelan perangkat. Saat perangkat Android menemukan tag NFC, perilaku yang diinginkan adalah membuat aktivitas yang paling sesuai menangani intent tanpa perlu bertanya kepada pengguna tentang aplikasi yang akan digunakan. Karena perangkat memindai tag NFC pada rentang yang sangat singkat, ada kemungkinan meminta pengguna memilih aktivitas secara manual akan membuatnya menjauhkan perangkat dari tag dan memutus koneksi. Anda harus mengembangkan aktivitas hanya untuk menangani tag NFC yang berkaitan dengan aktivitas Anda untuk mencegah Pemilih Aktivitas muncul.

Untuk membantu Anda melakukannya, Android menyediakan sistem pengiriman tag khusus yang menganalisis tag NFC yang dipindai, mengurainya, dan mencoba menemukan aplikasi berkaitan dengan data yang dipindai. Android melakukannya dengan:

  1. Mengurai tag NFC dan mencari tahu jenis MIME atau URI yang mengidentifikasi payload data dalam tag.
  2. Menggabungkan jenis MIME atau URI dan payload dalam satu intent. Dua langkah pertama ini dijelaskan dalam Cara tag NFC dipetakan ke jenis MIME dan URI.
  3. Memulai aktivitas berdasarkan intent. Hal ini dijelaskan dalam Cara Tag NFC Dikirim ke Aplikasi.

Cara tag NFC dipetakan ke jenis MIME dan URI

Sebelum mulai menulis aplikasi NFC, Anda perlu memahami jenis tag NFC yang berbeda, cara sistem pengiriman tag mengurai tag NFC, dan pekerjaan khusus yang dilakukan oleh sistem pengiriman tag saat mendeteksi pesan NDEF. Tag NFC hadir dalam beragam teknologi dan juga dapat berisi data yang ditulis dengan berbagai cara. Android memiliki dukungan terbanyak untuk standar NDEF, yang ditentukan oleh Forum NFC.

Data NDEF digabungkan dalam pesan (NdefMessage) yang berisi satu atau beberapa data (NdefRecord). Setiap data NDEF harus diformat dengan benar sesuai dengan spesifikasi jenis data yang ingin dibuat. Android juga mendukung jenis tag lain yang tidak berisi data NDEF, yang dapat Anda gunakan dengan class dalam paket android.nfc.tech. Untuk mempelajari teknologi ini lebih lanjut, lihat topik NFC Lanjutan. Penggunaan jenis tag lain melibatkan penulisan stack protokol Anda sendiri untuk berkomunikasi dengan tag. Oleh karena itu, sebaiknya gunakan NDEF jika memungkinkan untuk memudahkan pengembangan dan dukungan maksimum bagi perangkat Android.

Catatan: Untuk mendownload spesifikasi lengkap NDEF, buka situs Dokumen Aplikasi & Spesifikasi Forum NFC dan lihat Membuat jenis data NDEF umum untuk mengetahui contoh cara membuat data NDEF.

Setelah Anda memahami sedikit tentang tag NFC, bagian berikut menjelaskan secara lebih detail cara Android menangani tag berformat NDEF. Saat perangkat Android memindai tag NFC yang berisi data berformat NDEF, perangkat akan mengurai pesan dan mencoba mencari tahu jenis MIME atau URI identitas data tersebut. Untuk melakukannya, sistem akan membaca NdefRecord pertama dalam NdefMessage untuk menentukan cara menafsirkan seluruh pesan NDEF (pesan NDEF dapat memiliki beberapa data NDEF). Dalam pesan NDEF yang diformat dengan benar, NdefRecord pertama berisi kolom berikut:

TNF 3-bit (Format Nama Jenis)
Menunjukkan cara menafsirkan kolom jenis panjang variabel. Nilai yang valid dijelaskan dalam Tabel 1.
Jenis panjang variabel
Menjelaskan jenis data. Jika menggunakan TNF_WELL_KNOWN, gunakan kolom ini untuk menentukan Record Type Definition (RTD). Nilai RTD yang valid dijelaskan dalam Tabel 2.
ID panjang variabel
ID unik untuk data. Kolom ini jarang digunakan, tetapi jika perlu mengidentifikasi tag secara unik, Anda dapat membuat ID untuk tag tersebut.
Payload panjang variabel
Payload data sebenarnya yang ingin Anda baca atau tulis. Pesan NDEF dapat berisi beberapa data NDEF. Jadi, jangan berasumsi bahwa payload penuh berada dalam data NDEF pertama dari pesan NDEF.

Sistem pengiriman tag menggunakan kolom jenis dan TNF untuk mencoba memetakan jenis MIME atau URI ke pesan NDEF. Jika berhasil, sistem akan mengumpulkan informasi tersebut dalam intent ACTION_NDEF_DISCOVERED bersama dengan payload sebenarnya. Namun, ada kalanya sistem pengiriman tag tidak dapat menentukan jenis data berdasarkan data NDEF pertama. Hal ini terjadi jika data NDEF tidak dapat dipetakan ke jenis MIME atau URI, atau jika tag NFC tidak berisi data NDEF sejak awal. Dalam kasus tersebut, objek Tag yang memiliki informasi mengenai teknologi tag dan payload dikumpulkan dalam intent ACTION_TECH_DISCOVERED sebagai gantinya.

Tabel 1 menjelaskan cara sistem pengiriman tag memetakan kolom jenis dan TNF ke jenis MIME atau URI. Tabel ini juga menjelaskan TNF yang tidak dapat dipetakan ke jenis MIME atau URI. Dalam kasus ini, sistem pengiriman tag akan melakukan fallback ke ACTION_TECH_DISCOVERED.

Misalnya, jika sistem pengiriman tag menemukan data jenis TNF_ABSOLUTE_URI, sistem akan memetakan kolom jenis panjang variabel dari data tersebut ke URI. Sistem pengiriman tag mengumpulkan URI tersebut dalam kolom data intent ACTION_NDEF_DISCOVERED bersama dengan informasi lain tentang tag, seperti payload. Di sisi lain, jika menemukan data jenis TNF_UNKNOWN, sistem akan membuat intent yang mengumpulkan teknologi tag sebagai gantinya.

Tabel 1. TNF yang didukung dan pemetaannya

Format Nama Jenis (TNF) Pemetaan
TNF_ABSOLUTE_URI URI berdasarkan kolom jenis.
TNF_EMPTY Melakukan fallback ke ACTION_TECH_DISCOVERED.
TNF_EXTERNAL_TYPE URI berdasarkan URN dalam kolom jenis. URN dienkode dalam kolom jenis NDEF dalam bentuk yang disingkat: <domain_name>:<service_name>. Android memetakan URN ini ke URI dalam bentuk: vnd.android.nfc://ext/<domain_name>:<service_name>.
TNF_MIME_MEDIA Jenis MIME berdasarkan kolom jenis.
TNF_UNCHANGED Tidak valid dalam data pertama, sehingga melakukan fallback ke ACTION_TECH_DISCOVERED.
TNF_UNKNOWN Melakukan fallback ke ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWN Jenis MIME atau URI yang bergantung pada Record Type Definition (RTD), yang ditetapkan dalam kolom jenis. Lihat Tabel 2 untuk mengetahui informasi selengkapnya tentang RTD yang tersedia dan pemetaannya.

Tabel 2. RTD yang didukung untuk TNF_WELL_KNOWN dan pemetaannya

Record Type Definition (RTD) Pemetaan
RTD_ALTERNATIVE_CARRIER Melakukan fallback ke ACTION_TECH_DISCOVERED.
RTD_HANDOVER_CARRIER Melakukan fallback ke ACTION_TECH_DISCOVERED.
RTD_HANDOVER_REQUEST Melakukan fallback ke ACTION_TECH_DISCOVERED.
RTD_HANDOVER_SELECT Melakukan fallback ke ACTION_TECH_DISCOVERED.
RTD_SMART_POSTER URI berdasarkan penguraian payload.
RTD_TEXT Jenis MIME text/plain.
RTD_URI URI berdasarkan payload.

Cara pengiriman tag NFC ke aplikasi

Setelah membuat intent yang mengumpulkan tag NFC dan informasi identitasnya, sistem pengiriman tag akan mengirim intent tersebut ke aplikasi terkait yang memfilter intent tersebut. Jika ada lebih dari satu aplikasi yang dapat menangani intent, Pemilih Aktivitas akan ditampilkan sehingga pengguna dapat memilih Aktivitas. Sistem pengiriman tag mendefinisikan tiga intent, yang dicantumkan sesuai urutan prioritas tertinggi hingga terendah:

  1. ACTION_NDEF_DISCOVERED: Intent ini digunakan untuk memulai Aktivitas saat tag yang berisi payload NDEF dipindai dan dikenali jenisnya. Intent ini memiliki prioritas tertinggi, dan sistem pengiriman tag akan mencoba memulai Aktivitas menggunakan intent ini sebelum intent lainnya, jika memungkinkan.
  2. ACTION_TECH_DISCOVERED: Jika tidak ada aktivitas yang terdaftar untuk menangani intent ACTION_NDEF_DISCOVERED, sistem pengiriman tag akan mencoba memulai aplikasi dengan intent ini. Intent ini juga dimulai secara langsung (tanpa memulai ACTION_NDEF_DISCOVERED terlebih dahulu) jika tag yang dipindai berisi data NDEF yang tidak dapat dipetakan ke jenis MIME atau URI, atau jika tag tidak berisi data NDEF, tetapi merupakan teknologi tag yang dikenal.
  3. ACTION_TAG_DISCOVERED: Intent ini dimulai jika tidak ada aktivitas yang menangani intent ACTION_NDEF_DISCOVERED atau ACTION_TECH_DISCOVERED.

Cara kerja sistem pengiriman tag yang mendasar adalah sebagai berikut:

  1. Coba memulai Aktivitas dengan intent yang dibuat oleh sistem pengiriman tag saat menguraikan tag NFC (ACTION_NDEF_DISCOVERED atau ACTION_TECH_DISCOVERED).
  2. Jika tidak ada aktivitas yang memfilter intent tersebut, coba memulai Aktivitas menggunakan intent prioritas terendah berikutnya (ACTION_TECH_DISCOVERED atau ACTION_TAG_DISCOVERED) hingga aplikasi memfilter intent atau hingga sistem pengiriman tag mencoba semua intent yang memungkinkan.
  3. Jika tidak ada aplikasi yang memfilter intent apa pun, jangan lakukan apa pun.
Gambar 1. Sistem Pengiriman Tag

Jika memungkinkan, gunakan pesan NDEF dan intent ACTION_NDEF_DISCOVERED, karena intent ini bersifat paling spesifik di antara tiga intent yang ada. Dengan intent ini, Anda dapat memulai aplikasi pada waktu yang lebih tepat dibandingkan dua intent lainnya, sehingga pengguna akan mendapatkan pengalaman yang lebih baik.

Meminta akses NFC dalam manifes Android

Sebelum Anda dapat mengakses hardware NFC perangkat dan menangani intent NFC dengan benar, deklarasikan item ini dalam file AndroidManifest.xml:

  • Elemen <uses-permission> NFC untuk mengakses hardware NFC:
        <uses-permission android:name="android.permission.NFC" />
        
  • Versi SDK minimum yang dapat didukung oleh aplikasi Anda. API level 9 hanya mendukung pengiriman tag terbatas melalui ACTION_TAG_DISCOVERED, dan hanya memberi akses ke pesan NDEF melalui EXTRA_NDEF_MESSAGES tambahan. Tidak ada properti tag atau operasi I/O lain yang dapat diakses. API level 10 mencakup dukungan pembaca/penulis yang komprehensif serta push NDEF latar depan, dan API level 14 memudahkan pengiriman pesan NDEF ke perangkat lain dengan Android Beam dan metode sederhana lainnya untuk membuat data NDEF.
        <uses-sdk android:minSdkVersion="10"/>
        
  • Elemen uses-feature sehingga aplikasi Anda ditampilkan di Google Play hanya untuk perangkat yang memiliki hardware NFC:
        <uses-feature android:name="android.hardware.nfc" android:required="true" />
        

    Jika aplikasi Anda menggunakan fungsi NFC, tetapi fungsi tersebut tidak terlalu penting bagi aplikasi, Anda dapat menghilangkan elemen uses-feature dan memeriksa ketersediaan NFC pada waktu proses dengan mencari tahu apakah getDefaultAdapter() adalah null.

Memfilter intent NFC

Untuk memulai aplikasi saat tag NFC yang ingin ditangani sedang dipindai, aplikasi Anda dapat memfilter satu, dua, atau ketiga intent NFC dalam manifes Android. Namun, sebaiknya Anda memfilter intent ACTION_NDEF_DISCOVERED untuk mengontrol kapan aplikasi dimulai. Intent ACTION_TECH_DISCOVERED adalah fallback untuk ACTION_NDEF_DISCOVERED saat tidak ada aplikasi yang memfilter ACTION_NDEF_DISCOVERED atau saat payload bukan NDEF. Filter ACTION_TAG_DISCOVERED biasanya merupakan kategori filter yang terlalu umum. Banyak aplikasi akan memfilter ACTION_NDEF_DISCOVERED atau ACTION_TECH_DISCOVERED sebelum ACTION_TAG_DISCOVERED, sehingga probabilitas aplikasi Anda untuk dimulai cukup rendah. ACTION_TAG_DISCOVERED hanya tersedia sebagai upaya terakhir untuk memfilter aplikasi jika tidak ada aplikasi lain yang diinstal untuk menangani intent ACTION_NDEF_DISCOVERED atau ACTION_TECH_DISCOVERED.

Karena penerapan tag NFC bervariasi dan sering kali tidak dapat dikontrol, hal ini tidak selalu memungkinkan. Itulah sebabnya Anda dapat melakukan fallback ke dua intent lainnya jika diperlukan. Jika Anda memiliki kontrol atas jenis tag dan data yang ditulis, sebaiknya gunakan NDEF untuk memformat tag Anda. Bagian berikut menjelaskan cara memfilter setiap jenis intent.

ACTION_NDEF_DISCOVERED

Untuk memfilter intent ACTION_NDEF_DISCOVERED, deklarasikan filter intent bersama dengan jenis data yang ingin difilter. Contoh berikut memfilter intent ACTION_NDEF_DISCOVERED dengan jenis 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>
    

Contoh berikut memfilter URI dalam bentuk 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="http"
                  android:host="developer.android.com"
                  android:pathPrefix="/index.html" />
    </intent-filter>
    

ACTION_TECH_DISCOVERED

Jika aktivitas memfilter intent ACTION_TECH_DISCOVERED, Anda perlu membuat file resource XML yang menentukan teknologi yang didukung aktivitas Anda dalam kumpulan tech-list. Aktivitas Anda dianggap sesuai jika kumpulan tech-list adalah subset teknologi yang didukung oleh tag, yang bisa didapatkan dengan memanggil getTechList().

Misalnya, jika tag yang dipindai mendukung MifareClassic, NdefFormatable, dan NfcA, kumpulan tech-list Anda harus menentukan ketiga, dua, atau salah satu teknologi tersebut (dan bukan lainnya) agar aktivitas Anda dapat disesuaikan.

Contoh berikut menentukan semua teknologi. Anda dapat menghapus teknologi yang tidak diperlukan. Simpan file ini (Anda dapat memberi nama file sesuai keinginan) dalam folder <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>
    

Anda juga dapat menentukan beberapa kumpulan tech-list. Masing-masing kumpulan tech-list dianggap terpisah, dan aktivitas Anda dianggap sesuai jika ada satu kumpulan tech-list yang merupakan subset teknologi yang ditampilkan oleh getTechList(). Proses ini menyediakan semantik AND dan OR untuk teknologi yang sesuai. Contoh berikut menyesuaikan tag yang dapat mendukung teknologi NfcA dan Ndef atau dapat mendukung teknologi NfcB dan 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>
    

Dalam file AndroidManifest.xml, tentukan file resource yang baru saja dibuat di elemen <meta-data> dalam elemen <activity> seperti pada contoh berikut:

    <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>
    

Untuk mengetahui informasi selengkapnya tentang cara menggunakan teknologi tag dan intent ACTION_TECH_DISCOVERED, lihat Menggunakan Teknologi Tag yang Didukung dalam dokumen NFC Lanjutan.

ACTION_TAG_DISCOVERED

Untuk memfilter ACTION_TAG_DISCOVERED, gunakan filter intent berikut:

<intent-filter>
        <action android:name="android.nfc.action.TAG_DISCOVERED"/>
    </intent-filter>
    

Mendapatkan informasi dari intent

Jika aktivitas dimulai karena intent NFC, Anda dapat memperoleh informasi tentang tag NFC yang dipindai dari intent. Intent dapat berisi tambahan berikut bergantung pada tag yang dipindai:

Untuk mendapatkan tambahan ini, periksa apakah aktivitas Anda diluncurkan dengan salah satu intent NFC untuk memastikan bahwa tag dipindai, lalu dapatkan tambahan dari intent tersebut. Contoh berikut memeriksa intent ACTION_NDEF_DISCOVERED dan mendapatkan pesan NDEF dari intent tambahan.

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

Atau, Anda bisa mendapatkan objek Tag dari intent, yang akan berisi payload dan memungkinkan Anda menghitung teknologi tag:

Kotlin

    val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
    

Java

    Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    

Membuat jenis data NDEF yang umum

Bagian ini menjelaskan cara membuat jenis umum data NDEF untuk membantu Anda saat menulis ke tag NFC dan mengirim data dengan Android Beam. Mulai dari Android 4.0 (API level 14), metode createUri() tersedia untuk membantu Anda membuat data URI secara otomatis. Mulai dari Android 4.1 (API level 16), createExternal() dan createMime() tersedia untuk membantu Anda membuat data NDEF jenis eksternal dan MIME. Jika diperlukan, gunakan metode helper ini untuk menghindari kesalahan saat membuat data NDEF secara manual.

Bagian ini juga menjelaskan cara membuat filter intent yang sesuai untuk data tersebut. Semua contoh data NDEF ini harus berada dalam data NDEF pertama dari pesan NDEF yang Anda tulis ke tag atau beaming.

TNF_ABSOLUTE_URI

Catatan: Sebaiknya gunakan jenis RTD_URI, bukan TNF_ABSOLUTE_URI, karena lebih efisien.

Anda dapat membuat data NDEF TNF_ABSOLUTE_URI dengan cara berikut:

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

Filter intent untuk data NDEF sebelumnya akan terlihat seperti ini:

    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="http"
            android:host="developer.android.com"
            android:pathPrefix="/index.html" />
    </intent-filter>
    

TNF_MIME_MEDIA

Anda dapat membuat data NDEF TNF_MIME_MEDIA dengan cara berikut:

Menggunakan metode 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")));
    

Membuat NdefRecord secara manual:

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")));
    

Filter intent untuk data NDEF sebelumnya akan terlihat seperti ini:

    <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 dengan RTD_TEXT

Anda dapat membuat data NDEF TNF_WELL_KNOWN dengan cara berikut:

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

Filter intent untuk data NDEF sebelumnya akan terlihat seperti ini:

    <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 dengan RTD_URI

Anda dapat membuat data NDEF TNF_WELL_KNOWN dengan cara berikut:

Menggunakan metode createUri(String):

Kotlin

    val rtdUriRecord1 = NdefRecord.createUri("http://example.com")
    

Java

    NdefRecord rtdUriRecord1 = NdefRecord.createUri("http://example.com");
    

Menggunakan metode createUri(Uri):

Kotlin

    val rtdUriRecord2 = Uri.parse("http://example.com").let { uri ->
        NdefRecord.createUri(uri)
    }
    

Java

    Uri uri = Uri.parse("http://example.com");
    NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
    

Membuat NdefRecord secara manual:

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 http://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 http://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);
    

Filter intent untuk data NDEF sebelumnya akan terlihat seperti ini:

    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="http"
            android:host="example.com"
            android:pathPrefix="" />
    </intent-filter>
    

TNF_EXTERNAL_TYPE

Anda dapat membuat data NDEF TNF_EXTERNAL_TYPE dengan cara berikut:

Menggunakan metode 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);
    

Membuat NdefRecord secara manual:

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

Filter intent untuk data NDEF sebelumnya akan terlihat seperti ini:

    <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>
    

Gunakan TNF_EXTERNAL_TYPE untuk penerapan tag NFC yang lebih umum guna meningkatkan dukungan perangkat Android dan non-Android.

Catatan: URN untuk TNF_EXTERNAL_TYPE memiliki format kanonis: urn:nfc:ext:example.com:externalType, tetapi spesifikasi RTD Forum NFC mendeklarasikan bahwa bagian urn:nfc:ext: dari URN harus dihilangkan dari data NDEF. Oleh karena itu, Anda hanya perlu menyediakan domain (example.com dalam contoh) dan jenis (externalType dalam contoh) yang dipisahkan dengan tanda titik dua. Saat melakukan pengiriman TNF_EXTERNAL_TYPE, Android akan mengonversi URN urn:nfc:ext:example.com:externalType ke URI vnd.android.nfc://ext/example.com:externalType, yang dideklarasikan oleh filter intent dalam contoh.

Data aplikasi Android

Diperkenalkan di Android 4.0 (API level 14), Data Aplikasi Android (AAR) memberikan kepastian yang lebih kuat bahwa aplikasi Anda dimulai saat tag NFC dipindai. AAR memiliki nama paket aplikasi yang disematkan dalam data NDEF. Anda dapat menambahkan AAR ke data NDEF apa pun dari pesan NDEF, karena Android menelusuri AAR dalam seluruh pesan NDEF. Jika menemukan AAR, Android akan memulai aplikasi berdasarkan nama paket dalam AAR. Jika aplikasi tidak ada di perangkat, Google Play akan diluncurkan untuk mendownload aplikasi.

AAR berguna jika Anda ingin mencegah aplikasi lain memfilter intent yang sama dan kemungkinan menangani tag tertentu yang telah diterapkan. Karena adanya batasan nama paket, AAR hanya didukung di tingkat aplikasi, bukan di tingkat Aktivitas seperti filter intent. Jika Anda ingin menangani intent di tingkat Aktivitas, gunakan filter intent.

Jika tag berisi AAR, sistem pengiriman tag akan melakukan pengiriman dengan cara berikut:

  1. Cobalah memulai Aktivitas menggunakan filter intent seperti biasa. Jika Aktivitas yang sesuai dengan intent juga sesuai dengan AAR, mulai Aktivitas.
  2. Jika Aktivitas yang memfilter intent tidak sesuai dengan AAR, jika beberapa Aktivitas dapat menangani intent, atau jika tidak ada Aktivitas yang menangani intent, mulai aplikasi yang ditentukan oleh AAR.
  3. Jika tidak ada aplikasi yang dapat memulai dengan AAR, buka Google Play untuk mendownload aplikasi berdasarkan AAR.

Catatan: Anda dapat mengganti AAR dan sistem pengiriman intent dengan sistem pengiriman di latar depan, yang memungkinkan aktivitas latar depan diprioritaskan saat tag NFC ditemukan. Dengan metode ini, aktivitas harus berada di latar depan untuk mengganti AAR dan sistem pengiriman intent.

Jika tetap ingin memfilter tag yang dipindai yang tidak berisi AAR, Anda dapat mendeklarasikan filter intent seperti biasa. Hal ini berguna jika aplikasi Anda berkaitan dengan tag lain yang tidak berisi AAR. Misalnya, mungkin Anda ingin menjamin bahwa aplikasi menangani tag kepemilikan yang Anda terapkan serta tag umum yang diterapkan oleh pihak ketiga. Perlu diingat bahwa AAR ditujukan khusus untuk perangkat Android 4.0 atau yang lebih baru. Jadi, saat menerapkan tag, sebaiknya Anda menggunakan kombinasi jenis MIME/URI dan AAR untuk mendukung berbagai perangkat. Selain itu, saat menerapkan tag NFC, pikirkan cara menulis tag NFC untuk mengaktifkan dukungan bagi sebagian besar perangkat (perangkat Android dan lainnya). Anda dapat melakukannya dengan menentukan jenis MIME atau URI yang relatif unik untuk memudahkan aplikasi membedakannya.

Android menyediakan API sederhana untuk membuat AAR, yaitu createApplicationRecord(). Anda hanya perlu menyematkan AAR di mana pun dalam NdefMessage. Sebaiknya Anda tidak menggunakan data NdefMessage pertama, kecuali jika AAR adalah satu-satunya data dalam NdefMessage. Hal ini karena sistem Android memeriksa data pertama dari NdefMessage untuk menentukan jenis MIME atau URI tag, yang digunakan untuk membuat intent agar dapat difilter oleh aplikasi. Kode berikut menunjukkan cara membuat 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")}
            );
    )
    

Melakukan beaming pesan NDEF ke perangkat lain

Android Beam memungkinkan pertukaran data peer-to-peer yang sederhana antara dua perangkat Android. Aplikasi yang ingin melakukan beaming data ke perangkat lain harus berada di latar depan dan perangkat yang menerima data tidak boleh terkunci. Saat berada dalam jarak yang cukup dekat dengan perangkat penerima, perangkat yang melakukan beaming akan menampilkan UI "Sentuh untuk Melakukan Beaming". Kemudian, pengguna dapat memilih apakah akan melakukan beaming pesan ke perangkat penerima atau tidak.

Catatan: Pengiriman NDEF di latar depan tersedia di API level 10, yang menyediakan fungsi serupa dengan Android Beam. API ini sudah tidak digunakan lagi, tetapi tersedia untuk mendukung perangkat lama. Lihat enableForegroundNdefPush() untuk mengetahui informasi selengkapnya.

Anda dapat mengaktifkan Android Beam untuk aplikasi dengan memanggil salah satu dari dua metode berikut:

  • setNdefPushMessage(): Menerima NdefMessage untuk ditetapkan sebagai pesan yang akan di-beam. Otomatis melakukan beaming pesan saat dua perangkat berada dalam jarak yang cukup dekat.
  • setNdefPushMessageCallback(): Menerima callback yang berisi createNdefMessage() yang dipanggil saat perangkat berada dalam jangkauan untuk melakukan beaming data. Callback memungkinkan Anda hanya membuat pesan NDEF jika diperlukan.

Aktivitas hanya dapat mengirim pesan NDEF satu per satu, sehingga setNdefPushMessageCallback() akan didahulukan daripada setNdefPushMessage() jika keduanya ditetapkan. Untuk menggunakan Android Beam, semua panduan umum berikut harus dipenuhi:

  • Aktivitas yang melakukan beaming data harus berada di latar depan. Layar kedua perangkat harus terbuka kuncinya.
  • Anda harus mengumpulkan data yang akan di-beam dalam objek NdefMessage.
  • Perangkat NFC yang menerima data yang di-beam harus mendukung protokol push NDEF com.android.npp atau SNEP (Simple NDEF Exchange Protocol) Forum NFC. Protokol com.android.npp diperlukan untuk perangkat di API level 9 (Android 2.3) hingga API level 13 (Android 3.2). com.android.npp dan SNEP diperlukan di API level 14 (Android 4.0) dan yang lebih baru.

Catatan: Jika aktivitas Anda mengaktifkan Android Beam dan berada di latar depan, sistem pengiriman intent standar akan dinonaktifkan. Namun, jika aktivitas Anda juga mengaktifkan pengiriman latar depan, sistem tetap dapat memindai tag yang sesuai dengan filter intent yang ditetapkan di pengiriman latar depan.

Untuk mengaktifkan Android Beam:

  1. Buat NdefMessage yang berisi NdefRecord yang ingin dikirim ke perangkat lain.
  2. Panggil setNdefPushMessage() dengan NdefMessage atau panggil setNdefPushMessageCallback yang meneruskan objek NfcAdapter.CreateNdefMessageCallback dalam metode onCreate() aktivitas Anda. Metode ini memerlukan setidaknya satu aktivitas yang ingin diaktifkan dengan Android Beam, dan daftar opsional aktivitas lain yang ingin diaktifkan.

    Umumnya, Anda menggunakan setNdefPushMessage() jika Aktivitas hanya perlu mengirim pesan NDEF yang sama sepanjang waktu, saat dua perangkat berada dalam jangkauan untuk berkomunikasi. Anda menggunakan setNdefPushMessageCallback saat aplikasi memperhatikan konteks aplikasi saat ini dan ingin mengirim pesan NDEF bergantung pada aktivitas pengguna di aplikasi Anda.

Contoh berikut menunjukkan cara aktivitas sederhana memanggil NfcAdapter.CreateNdefMessageCallback dalam metode onCreate() aktivitas (lihat AndroidBeamDemo untuk contoh lengkapnya). Contoh ini juga memiliki metode untuk membantu Anda membuat data MIME:

Kotlin

    package com.example.android.beam

    import android.app.Activity
    import android.content.Intent
    import android.nfc.NdefMessage
    import android.nfc.NdefRecord
    import android.nfc.NfcAdapter
    import android.nfc.NfcAdapter.CreateNdefMessageCallback
    import android.nfc.NfcEvent
    import android.os.Bundle
    import android.os.Parcelable
    import android.widget.TextView
    import android.widget.Toast
    import java.nio.charset.Charset

    class Beam : Activity(), NfcAdapter.CreateNdefMessageCallback {

        private var nfcAdapter: NfcAdapter? = null
        private lateinit var textView: TextView

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.main)
            textView = findViewById(R.id.textView)
            // Check for available NFC Adapter
            nfcAdapter = NfcAdapter.getDefaultAdapter(this)
            if (nfcAdapter == null) {
                Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show()
                finish()
                return
            }
            // Register callback
            nfcAdapter?.setNdefPushMessageCallback(this, this)
        }

        override fun createNdefMessage(event: NfcEvent): NdefMessage {
            val text = "Beam me up, Android!\n\n" +
                    "Beam Time: " + System.currentTimeMillis()
            return NdefMessage(
                    arrayOf(
                            createMime("application/vnd.com.example.android.beam", text.toByteArray())
                    )
                    /**
                     * The Android Application Record (AAR) is commented out. When a device
                     * receives a push with an AAR in it, the application specified in the AAR
                     * is guaranteed to run. The AAR overrides the tag dispatch system.
                     * You can add it back in to guarantee that this
                     * activity starts when receiving a beamed message. For now, this code
                     * uses the tag dispatch system.
                     *///,NdefRecord.createApplicationRecord("com.example.android.beam")
            )
        }

        override fun onResume() {
            super.onResume()
            // Check to see that the Activity started due to an Android Beam
            if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
                processIntent(intent)
            }
        }

        override fun onNewIntent(intent: Intent) {
            // onResume gets called after this to handle the intent
            setIntent(intent)
        }

        /**
         * Parses the NDEF Message from the intent and prints to the TextView
         */
        private fun processIntent(intent: Intent) {
            textView = findViewById(R.id.textView)
            // only one message sent during the beam
            intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMsgs ->
                (rawMsgs[0] as NdefMessage).apply {
                    // record 0 contains the MIME type, record 1 is the AAR, if present
                    textView.text = String(records[0].payload)
                }
            }
        }
    }
    

Java

    package com.example.android.beam;

    import android.app.Activity;
    import android.content.Intent;
    import android.nfc.NdefMessage;
    import android.nfc.NdefRecord;
    import android.nfc.NfcAdapter;
    import android.nfc.NfcAdapter.CreateNdefMessageCallback;
    import android.nfc.NfcEvent;
    import android.os.Bundle;
    import android.os.Parcelable;
    import android.widget.TextView;
    import android.widget.Toast;
    import java.nio.charset.Charset;

    public class Beam extends Activity implements CreateNdefMessageCallback {
        NfcAdapter nfcAdapter;
        TextView textView;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            TextView textView = (TextView) findViewById(R.id.textView);
            // Check for available NFC Adapter
            nfcAdapter = NfcAdapter.getDefaultAdapter(this);
            if (nfcAdapter == null) {
                Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
                finish();
                return;
            }
            // Register callback
            nfcAdapter.setNdefPushMessageCallback(this, this);
        }

        @Override
        public NdefMessage createNdefMessage(NfcEvent event) {
            String text = ("Beam me up, Android!\n\n" +
                    "Beam Time: " + System.currentTimeMillis());
            NdefMessage msg = new NdefMessage(
                    new NdefRecord[] { createMime(
                            "application/vnd.com.example.android.beam", text.getBytes())
             /**
              * The Android Application Record (AAR) is commented out. When a device
              * receives a push with an AAR in it, the application specified in the AAR
              * is guaranteed to run. The AAR overrides the tag dispatch system.
              * You can add it back in to guarantee that this
              * activity starts when receiving a beamed message. For now, this code
              * uses the tag dispatch system.
              */
              //,NdefRecord.createApplicationRecord("com.example.android.beam")
            });
            return msg;
        }

        @Override
        public void onResume() {
            super.onResume();
            // Check to see that the Activity started due to an Android Beam
            if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
                processIntent(getIntent());
            }
        }

        @Override
        public void onNewIntent(Intent intent) {
            // onResume gets called after this to handle the intent
            setIntent(intent);
        }

        /**
         * Parses the NDEF Message from the intent and prints to the TextView
         */
        void processIntent(Intent intent) {
            textView = (TextView) findViewById(R.id.textView);
            Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                    NfcAdapter.EXTRA_NDEF_MESSAGES);
            // only one message sent during the beam
            NdefMessage msg = (NdefMessage) rawMsgs[0];
            // record 0 contains the MIME type, record 1 is the AAR, if present
            textView.setText(new String(msg.getRecords()[0].getPayload()));
        }
    }
    

Perhatikan bahwa kode ini berisi komentar AAR yang dapat dihapus. Jika Anda mengaktifkan AAR, aplikasi yang ditentukan dalam AAR selalu menerima pesan Android Beam. Jika aplikasi tidak ada, Google Play akan mulai mendownload aplikasi. Oleh karena itu, filter intent berikut secara teknis tidak diperlukan untuk perangkat Android 4.0 atau yang lebih baru jika AAR digunakan:

    <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>
    

Dengan filter intent ini, aplikasi com.example.android.beam sekarang dapat dimulai saat memindai tag NFC atau menerima Android Beam dengan jenis AAR , atau saat pesan berformat NDEF berisi data MIME jenis application/vnd.com.example.android.beam.

Meskipun AAR menjamin aplikasi akan dimulai atau didownload, filter intent direkomendasikan karena memungkinkan Anda memulai Aktivitas pilihan Anda dalam aplikasi, sehingga tidak perlu selalu memulai Aktivitas utama dalam paket yang ditentukan oleh AAR. AAR tidak memiliki perincian tingkat Aktivitas. Selain itu, karena beberapa perangkat Android tidak mendukung AAR, Anda juga perlu menyematkan informasi identitas dalam data NDEF pertama dari pesan NDEF dan memfilternya juga, untuk berjaga-jaga. Lihat Membuat Jenis Data NDEF Umum untuk mengetahui informasi selengkapnya tentang cara membuat data.