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 dan menjelaskan API framework Android yang mendukung fitur-fitur ini. Untuk topik lanjutan, termasuk diskusi tentang cara bekerja dengan 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 BeamTM

Membaca data NDEF dari tag NFC ditangani dengan pengiriman tag , yang menganalisis tag NFC yang ditemukan, mengategorikan data dengan tepat, dan memulai aplikasi yang tertarik dengan data yang dikategorikan. Sebuah aplikasi yang ingin menangani tag NFC yang dipindai dapat mendeklarasikan filter intent dan untuk menangani data itu.

Fitur Android BeamTM memungkinkan perangkat mengirim pesan NDEF perangkat lain dengan mengetuk perangkat secara fisik. Interaksi ini memberikan cara yang lebih mudah untuk mengirim data dibandingkan teknologi nirkabel lainnya seperti Bluetooth, karena dengan NFC, tidak ada perangkat manual penemuan atau pemasangan. Koneksi dimulai secara otomatis ketika dua perangkat terhubung ke dalam rentang. Android Beam tersedia melalui serangkaian API NFC, sehingga aplikasi apa pun dapat mentransmisikan informasi antar perangkat. Misalnya, aplikasi Kontak, Browser, dan YouTube menggunakan Android Beam untuk berbagi kontak, halaman web, dan video dengan perangkat lain.

Sistem pengiriman tag

Perangkat Android biasanya mencari tag NFC saat layar tidak terkunci, kecuali NFC dinonaktifkan di menu Setelan perangkat. Saat perangkat Android menemukan tag NFC, perilaku yang diinginkan adalah membuat aktivitas yang paling tepat menangani intent tanpa bertanya kepada pengguna aplikasi apa untuk digunakan. Karena perangkat memindai tag NFC pada jarak yang sangat pendek, ada kemungkinan bahwa membuat pengguna secara manual memilih aktivitas yang akan memaksa pengguna menjauhkan perangkat dari tag dan memutus koneksi. Anda harus mengembangkan aktivitas untuk hanya menangani tag NFC yang penting untuk aktivitas Anda mencegah Pemilih Aktivitas muncul.

Untuk membantu Anda mencapai sasaran ini, Android menyediakan sistem pengiriman tag khusus yang menganalisis pemindaian Tag NFC, menguraikannya, dan mencoba menemukan aplikasi yang tertarik dengan data yang dipindai. Ini melakukannya dengan:

  1. Mengurai tag NFC dan mencari tahu jenis MIME atau URI yang mengidentifikasi payload data di tag.
  2. Menggabungkan jenis MIME atau URI dan payload dalam satu intent. Dua pertama ini langkah-langkahnya 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 Anda mulai menulis aplikasi NFC, penting untuk memahami jenis tag NFC, bagaimana sistem pengiriman tag mengurai tag NFC, dan pekerjaan khusus yang dilakukan tag dilakukan ketika mendeteksi pesan NDEF. Tag NFC tersedia dalam beragam teknologi dan juga dapat menulis data dengan berbagai cara. Android memiliki dukungan terbanyak untuk standar NDEF, yang ditentukan oleh Forum NFC.

Data NDEF dienkapsulasi dalam pesan (NdefMessage) yang berisi satu data atau lebih (NdefRecord). Setiap catatan NDEF harus disusun dengan baik sesuai dengan spesifikasi jenis catatan yang ingin Anda buat. Android juga mendukung jenis tag lain yang tidak berisi data NDEF, yang dapat Anda gunakan dengan class dalam paket android.nfc.tech. Untuk mempelajari lebih lanjut terkait teknologi ini, lihat topik NFC Lanjutan. Bekerja dengan jenis tag lain ini melibatkan menulis tumpukan protokol Anda sendiri untuk berkomunikasi dengan tag, jadi kami sarankan menggunakan NDEF saat mungkin untuk kemudahan pengembangan dan dukungan maksimum untuk perangkat yang didukung Android.

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

Sekarang setelah Anda memiliki pengetahuan tentang tag NFC, bagian berikut ini menjelaskan secara lebih rinci bagaimana Android menangani tag berformat NDEF. Saat perangkat Android memindai tag NFC yang berisi NDEF data berformat, ia mengurai pesan dan mencoba mencari tahu tipe MIME data atau URI. Untuk melakukannya, sistem akan membaca NdefRecord pertama di dalam NdefMessage untuk menentukan cara menafsirkan seluruh pesan NDEF (pesan NDEF dapat memiliki beberapa data NDEF). Dalam pesan NDEF yang disusun dengan baik, NdefRecord pertama berisi kolom berikut:

TNF 3-bit (Format Nama Jenis)
Menunjukkan cara menafsirkan kolom jenis panjang variabel. Nilai yang valid adalah yang dijelaskan dalam Tabel 1.
Jenis panjang variabel
Menjelaskan jenis data. Jika menggunakan TNF_WELL_KNOWN, gunakan untuk menentukan Record Type Definition (RTD). Nilai RTD yang valid dijelaskan dalam Tabel 2.
ID panjang variabel
ID unik untuk data. Bidang ini tidak sering 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. NDEF pesan dapat berisi beberapa data NDEF, jadi jangan berasumsi bahwa payload penuh berada di NDEF pertama untuk rekaman 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 demikian, ada adalah saat sistem pengiriman tag tidak dapat menentukan jenis data berdasarkan NDEF pertama data. Ini terjadi jika data NDEF tidak dapat dipetakan ke jenis MIME atau URI, atau ketika Awalnya, tag NFC tidak berisi data NDEF. Dalam kasus tersebut, objek Tag yang memiliki informasi tentang teknologi tag dan payload akan dienkapsulasi di dalam intent ACTION_TECH_DISCOVERED.

Tabel 1 menjelaskan cara sistem pengiriman tag memetakan TNF dan jenis kolom 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 kembali ke ACTION_TECH_DISCOVERED.

Misalnya, jika sistem pengiriman tag menemukan data jenis TNF_ABSOLUTE_URI, sistem akan memetakan kolom jenis panjang variabel dari kumpulan data tersebut ke dalam URI. Sistem pengiriman tag mengenkapsulasi 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, peristiwa ini akan membuat intent yang mengenkapsulasi 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 ke isian tipe NDEF di bentuk yang dipersingkat: <domain_name>:<service_name>. Android memetakan 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 catatan pertama, jadi kembali 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 {i>type<i}. Lihat Tabel 2 untuk informasi selengkapnya tentang RTD yang tersedia dan pemetaannya.

Tabel 2. RTD yang didukung untuk TNF_WELL_KNOWN dan pemetaan

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

Saat sistem pengiriman tag selesai membuat intent yang mengenkapsulasi tag NFC dan informasi pengenal, ia mengirimkan maksud ke aplikasi terkait yang filter untuk intent. Jika ada lebih dari satu aplikasi yang bisa menangani intent, Pemilih Aktivitas ditampilkan sehingga pengguna dapat memilih Aktivitas. Sistem pengiriman tag mendefinisikan tiga intent, yang tercantum dengan urutan dari prioritas tertinggi hingga terendah:

  1. ACTION_NDEF_DISCOVERED: Intent ini digunakan untuk memulai Aktivitas saat tag yang berisi payload NDEF dipindai dan merupakan jenis yang dikenali. Ini adalah intent prioritas tertinggi, dan sistem pengiriman tag mencoba memulai Aktivitas dengan sebelum intent lainnya, bila memungkinkan.
  2. ACTION_TECH_DISCOVERED: Jika tidak ada aktivitas yang terdaftar menangani ACTION_NDEF_DISCOVERED sistem pengiriman tag akan mencoba memulai aplikasi dengan intent ini. Ini intent juga langsung dimulai (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 NDEF data tetapi merupakan teknologi tag yang dikenal.
  3. ACTION_TAG_DISCOVERED: Intent ini dimulai jika tidak ada aktivitas yang menangani ACTION_NDEF_DISCOVERED atau ACTION_TECH_DISCOVERED intent.

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 (baik ACTION_NDEF_DISCOVERED atau ACTION_TECH_DISCOVERED).
  2. Jika tidak ada aktivitas yang memfilter intent tersebut, cobalah memulai Aktivitas dengan intent prioritas terendah (ACTION_TECH_DISCOVERED atau ACTION_TAG_DISCOVERED) hingga aplikasi memfilter untuk intent atau hingga sistem pengiriman tag mencoba semua kemungkinan intent.
  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 ini adalah yang paling spesifik dari ketiganya. Intent ini memungkinkan Anda memulai aplikasi pada waktu yang lebih tepat daripada dua intent lainnya, akan memberikan pengalaman pengguna yang lebih baik.

Meminta akses NFC dalam manifes Android

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

  • 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 tambahan EXTRA_NDEF_MESSAGES. Lain kali properti tag lainnya atau operasi I/O dapat diakses. Level API 10 mencakup dukungan pembaca/penulis yang komprehensif serta dorongan NDEF latar depan, dan level API 14 menyediakan cara yang lebih mudah untuk mengirim pesan NDEF ke perangkat lain dengan Android Beam dan lainnya metode praktis untuk membuat catatan NDEF.
    <uses-sdk android:minSdkVersion="10"/>
    
  • Elemen uses-feature agar aplikasi Anda muncul 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 itu tidak penting bagi aplikasi, Anda dapat menghilangkan elemen uses-feature dan memeriksa ketersediaan NFC di runtime dengan memeriksa apakah getDefaultAdapter() adalah null.

Memfilter intent NFC

Untuk memulai aplikasi saat tag NFC yang ingin Anda tangani dipindai, aplikasi Anda dapat memfilter satu, dua, atau ketiga intent NFC dalam manifes Android. Namun, Anda biasanya ingin memfilter intent ACTION_NDEF_DISCOVERED untuk mengontrol kapan aplikasi Anda dimulai. Intent ACTION_TECH_DISCOVERED adalah penggantian untuk ACTION_NDEF_DISCOVERED saat tidak ada aplikasi yang memfilter ACTION_NDEF_DISCOVERED atau saat payload tidak NDEF. Pemfilteran untuk ACTION_TAG_DISCOVERED biasanya terlalu umum untuk kategori yang akan difilter. Banyak aplikasi akan memfilter ACTION_NDEF_DISCOVERED atau ACTION_TECH_DISCOVERED sebelum ACTION_TAG_DISCOVERED, sehingga aplikasi Anda memiliki probabilitas rendah memulai. ACTION_TAG_DISCOVERED hanya tersedia sebagai opsi terakhir untuk difilter oleh aplikasi jika tidak ada aplikasi lain yang diinstal untuk menangani ACTION_NDEF_DISCOVERED atau ACTION_TECH_DISCOVERED.

Karena penerapan tag NFC bervariasi dan sering kali tidak berada di bawah kendali Anda, hal ini tidak selalu memungkinkan, itulah sebabnya Anda bisa kembali ke dua intent lainnya bila diperlukan. Bila Anda memiliki jenis tag dan data yang ditulis, sebaiknya Anda menggunakan NDEF untuk memformat {i>tag<i}. Bagian berikut menjelaskan cara memfilter setiap jenis intent.

ACTION_NDEF_DISCOVERED

Untuk memfilter intent ACTION_NDEF_DISCOVERED, deklarasikan atribut filter intent bersama dengan jenis data yang ingin Anda filter. Tujuan contoh filter berikut untuk ACTION_NDEF_DISCOVERED intent 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="https"
              android:host="developer.android.com"
              android:pathPrefix="/index.html" />
</intent-filter>

ACTION_TECH_DISCOVERED

Jika aktivitas Anda memfilter intent ACTION_TECH_DISCOVERED, Anda harus membuat file sumber daya XML yang menetapkan teknologi yang didukung aktivitas Anda dalam kumpulan tech-list. Aktivitas Anda adalah dianggap cocok jika kumpulan tech-list merupakan subset teknologi yang didukung oleh tag, yang dapat Anda peroleh dengan memanggil getTechList().

Misalnya, jika tag yang dipindai mendukung Mifare Classic, NdefFormatable, dan NfcA, Kumpulan tech-list harus menentukan ketiga, dua, atau salah satu teknologi tersebut (dan tidak ada else) agar aktivitas Anda dapat dicocokkan.

Contoh berikut menentukan semua teknologi. Anda harus menghapus layanan yang tidak didukung oleh tag NFC Anda. Simpan file ini (Anda bisa menamainya apa pun yang Anda inginkan) di 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. Setiap tech-list kumpulan dianggap terpisah, dan aktivitas Anda dianggap cocok jika ada satu Kumpulan tech-list adalah subset teknologi yang ditampilkan oleh getTechList(). Fungsi ini menyediakan AND dan OR semantik untuk teknologi pencocokan. Contoh berikut cocok dengan 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>

Di file AndroidManifest.xml, tentukan file resource yang baru saja Anda buat di elemen <meta-data> di dalam <activity> seperti dalam 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 informasi selengkapnya tentang cara menggunakan teknologi tag dan maksud ACTION_TECH_DISCOVERED, lihat Bekerja dengan Tag yang Didukung Teknologi dalam dokumen NFC Lanjutan.

ACTION_TAG_DISCOVERED

Untuk memfilter ACTION_TAG_DISCOVERED, gunakan intent berikut filter:

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

Mendapatkan informasi dari intent

Jika aktivitas dimulai karena intent NFC, Anda bisa mendapatkan informasi tentang NFC yang dipindai tag 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 telah dipindai, lalu dapatkan bagian tambahan dari intent. Contoh berikut memeriksa ACTION_NDEF_DISCOVERED intent dan mendapatkan pesan NDEF dari ekstra intent.

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 data NDEF umum untuk membantu Anda saat menulis ke Tag NFC atau mengirim data dengan Android Beam. Mulai Android 4.0 (API level 14), Metode createUri() tersedia untuk membantu Anda membuat Data URI secara otomatis. Mulai Android 4.1 (API level 16), createExternal() dan createMime() tersedia untuk membantu Anda membuat Data NDEF jenis eksternal dan MIME. Gunakan metode bantuan ini bila memungkinkan untuk menghindari kesalahan saat membuat catatan NDEF secara manual.

Bagian ini juga menjelaskan cara membuat filter intent untuk kumpulan data tersebut. Semua contoh data NDEF ini harus ada dalam NDEF pertama catatan pesan NDEF yang Anda tulis ke {i>tag<i} atau {i>beaming<i}.

TNF_ABSOLUTE_URI

Catatan: Sebaiknya gunakan Ketik RTD_URI sebagai gantinya dari 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="https"
        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("https://example.com")

Java

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

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

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

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="https"
        android:host="example.com"
        android:pathPrefix="" />
</intent-filter>

TNF_EXTERNAL_TYPE

Anda dapat membuat data NDEF TNF_EXTERNAL_TYPE dengan mengikuti cara:

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 deployment tag NFC yang lebih umum guna mendukung keduanya dengan lebih baik Perangkat yang didukung 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. Jadi, Anda hanya perlu menyediakan domain (example.com dalam contoh) dan jenis (dalam contoh externalType) yang dipisahkan dengan titik dua. Saat mengirim TNF_EXTERNAL_TYPE, Android akan mengonversi URN urn:nfc:ext:example.com:externalType menjadi URI vnd.android.nfc://ext/example.com:externalType, yang merupakan filter intent dalam contoh mendeklarasikannya.

Data aplikasi Android

Diperkenalkan di Android 4.0 (API level 14), Catatan Aplikasi Android (AAR) memberikan kepastian bahwa aplikasi Anda dimulai saat tag NFC dipindai. AAR memiliki nama paket aplikasi yang disematkan di dalam catatan NDEF. Anda dapat menambahkan AAR ke data NDEF apa pun dari 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 diluncurkan untuk mengunduh aplikasi.

AAR berguna jika Anda ingin mencegah aplikasi lain memfilter intent yang sama dan dan dapat menangani tag tertentu yang telah di-deploy. AAR hanya didukung di aplikasi, karena adanya batasan nama paket, dan bukan di level Activity seperti pada pemfilteran 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 intent juga sesuai dengan AAR, mulai Aktivitas.
  2. Jika Aktivitas yang memfilter intent tidak cocok 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 latar depan sistem pengiriman, 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 masih ingin memfilter tag yang dipindai yang tidak berisi AAR, Anda dapat mendeklarasikan filter intent seperti biasa. Hal ini berguna jika aplikasi Anda tertarik dengan tag lain yang tidak berisi AAR. Misalnya, mungkin Anda ingin menjamin aplikasi Anda menangani tag eksklusif yang Anda terapkan serta tag umum yang diterapkan oleh pihak ketiga. Harap diingat AAR khusus untuk perangkat Android 4.0 atau yang lebih baru. Jadi, saat men-deploy tag, kemungkinan besar Anda ingin untuk menggunakan kombinasi AAR dan jenis/URI MIME untuk mendukung beragam perangkat. Di beberapa Saat Anda menerapkan tag NFC, pikirkan bagaimana Anda akan menulis tag NFC untuk mengaktifkan mendukung sebagian besar perangkat (perangkat berteknologi Android dan perangkat lainnya). Anda dapat melakukannya dengan mendefinisikan jenis MIME atau URI yang relatif unik untuk memudahkan aplikasi membedakannya.

Android menyediakan API sederhana untuk membuat AAR, createApplicationRecord(). Yang Anda perlukan untuk adalah menyematkan AAR di mana saja dalam NdefMessage. Anda tidak ingin untuk menggunakan data pertama NdefMessage, kecuali jika AAR adalah satu-satunya rekam di NdefMessage. Hal ini karena Android sistem memeriksa data pertama NdefMessage untuk menentukan jenis MIME atau URI tag, yang digunakan untuk membuat intent yang akan 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. Tujuan aplikasi yang ingin melakukan beaming data ke perangkat lain harus berada di latar depan dan perangkat yang menerima data tidak boleh terkunci. Saat perangkat beaming bersentuhan cukup dekat dengan perangkat penerima, perangkat yang melakukan beaming akan menampilkan tombol "Sentuh untuk Melakukan Beaming" UI. Kemudian pengguna dapat memilih apakah mengirimkan 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 yang tersedia untuk mendukung perangkat yang lebih 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. Melakukan beaming pesan secara otomatis ketika dua perangkat berada dalam jarak yang cukup dekat.
  • setNdefPushMessageCallback(): Menerima callback yang berisi createNdefMessage() yang dipanggil saat perangkat berada dalam jangkauan untuk memancarkan data. Callback memungkinkan Anda membuat pesan NDEF hanya jika diperlukan.

Suatu aktivitas hanya dapat mengirim satu pesan NDEF pada satu waktu, sehingga setNdefPushMessageCallback() lebih diprioritaskan lebih dari setNdefPushMessage() jika keduanya ditetapkan. Untuk menggunakan Android Beam, panduan umum berikut harus dipenuhi:

  • Aktivitas yang melakukan beaming data harus berada di latar depan. Kedua perangkat harus memiliki layar mereka terbuka.
  • Anda harus mengenkapsulasi data yang di-beam dalam NdefMessage .
  • Perangkat NFC yang menerima data yang di-beam harus mendukung com.android.npp Protokol push NDEF atau SNEP Forum NFC (Simple NDEF Exchange Protokol). Protokol com.android.npp diperlukan untuk perangkat di API level 9 (Android 2.3) ke level API 13 (Android 3.2). com.android.npp dan SNEP diwajibkan di Level API 14 (Android 4.0) dan yang lebih baru.

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

Untuk mengaktifkan Android Beam:

  1. Membuat NdefMessage yang berisi NdefRecord yang ingin Anda dorong ke perangkat lain.
  2. Panggil setNdefPushMessage() dengan NdefMessage atau panggil setNdefPushMessageCallback yang meneruskan objek NfcAdapter.CreateNdefMessageCallback di metode onCreate() aktivitas Anda. Metode ini memerlukan setidaknya satu aktivitas yang ingin Anda aktifkan dengan Android Beam, bersama dengan daftar opsional aktivitas lain untuk diaktifkan.

    Secara umum, Anda biasanya menggunakan setNdefPushMessage() jika Aktivitas Anda hanya perlu mengirim pesan NDEF yang sama setiap saat, saat dua perangkat berada dalam jangkauan untuk berkomunikasi. Anda menggunakan setNdefPushMessageCallback saat aplikasi peduli dengan konteks aplikasi saat ini dan ingin mengirim pesan NDEF tergantung pada apa yang pengguna lakukan dalam aplikasi Anda.

Contoh berikut menunjukkan cara aktivitas sederhana memanggil NfcAdapter.CreateNdefMessageCallback dalam metode onCreate() aktivitas (lihat AndroidBeamDemo untuk sampel 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 saat ini, Google Play akan mulai mendownload aplikasi. Oleh karena itu, 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 kini dapat dimulai saat memindai tag NFC atau menerima Android Beam dengan AAR jenis com.example.android.beam, atau jika pesan berformat NDEF berisi data MIME dari jenis application/vnd.com.example.android.beam.

Meskipun AAR menjamin aplikasi dimulai atau didownload, filter intent direkomendasikan, karena memungkinkan Anda memulai Aktivitas pilihan Anda di aplikasi daripada selalu memulai Aktivitas utama dalam paket yang ditentukan oleh AAR. AAR tidak memiliki perincian tingkat Aktivitas. Juga, karena beberapa perangkat berbasis Android tidak mendukung AAR, Anda juga harus menyematkan informasi identitas dalam data NDEF pertama NDEF pesan dan juga memfilternya, untuk berjaga-jaga. Lihat Membuat Jenis data NDEF untuk mengetahui informasi lebih lanjut tentang cara membuat kumpulan data.