Android reading from NFC tag
1. Create a nfc filter xml file at res/xml/nfc_tech_filter.xml
android.nfc.tech.Ndef
2. Add android.permission.NFC in AndroidManifest.xml
3. In AndroidManifest.xml, inside the activity tag for the activity you want to launch for reading NFC, add following filter intent and meta-data.
4. The entire AndroidManifest.xml should look like this after step 2 and step 3 are completed.
5. activity_main.xml, the layout file for the MainActivity with a TextView for displaying message read from NFC tag.
6. MainActivity.kt, the code for reading and displaying text message from NFC tag.
package com.codexpedia.nfcreader
import android.app.Activity
import android.app.PendingIntent
import android.content.Intent
import android.content.IntentFilter
import android.nfc.*
import android.os.Bundle
import android.os.Parcelable
import android.util.Log
import android.widget.TextView
import android.widget.Toast
import com.codexpedia.nfcreader.databinding.ActivityMainBinding
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset
import kotlin.experimental.and
class MainActivity : Activity() {
lateinit var writeTagFilters: Array
private lateinit var tvNFCContent: TextView
private lateinit var binding: ActivityMainBinding
var nfcAdapter: NfcAdapter? = null
var pendingIntent: PendingIntent? = null
var myTag: Tag? = null
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
tvNFCContent = binding.nfcContents
tvNFCContent.text = "Place the back of the phone over a NFC tag to read message from NFC tag"
nfcAdapter = NfcAdapter.getDefaultAdapter(this)
if (nfcAdapter == null) {
// Stop here, we definitely need NFC
Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show()
finish()
}
//This is for when the activity is launched by the intent-filter for android.nfc.action.NDEF_DISCOVERE
readFromIntent(intent)
pendingIntent = PendingIntent.getActivity(
this,
0,
Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
0
)
val tagDetected = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
tagDetected.addCategory(Intent.CATEGORY_DEFAULT)
writeTagFilters = arrayOf(tagDetected)
}
/******************************************************************************
* Read From NFC Tag
****************************/
private fun readFromIntent(intent: Intent) {
val action = intent.action
if (NfcAdapter.ACTION_TAG_DISCOVERED == action || NfcAdapter.ACTION_TECH_DISCOVERED == action || NfcAdapter.ACTION_NDEF_DISCOVERED == action) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG) as Tag?
val rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
var msgs = mutableListOf()
if (rawMsgs != null) {
for (i in rawMsgs.indices) {
msgs.add(i, rawMsgs[i] as NdefMessage)
}
buildTagViews(msgs.toTypedArray())
}
}
}
private fun buildTagViews(msgs: Array) {
if (msgs == null || msgs.isEmpty()) return
var text = ""
val payload = msgs[0].records[0].payload
val textEncoding: Charset = if ((payload[0] and 128.toByte()).toInt() == 0) Charsets.UTF_8 else Charsets.UTF_16 // Get the Text Encoding
val languageCodeLength: Int = (payload[0] and 51).toInt() // Get the Language Code, e.g. "en"
try {
// Get the Text
text = String(
payload,
languageCodeLength + 1,
payload.size - languageCodeLength - 1,
textEncoding
)
} catch (e: UnsupportedEncodingException) {
Log.e("UnsupportedEncoding", e.toString())
}
tvNFCContent.text = "Message read from NFC Tag:\n $text"
}
/**
* This is for reading the NFC when the app is already launched
*/
override fun onNewIntent(intent: Intent) {
setIntent(intent)
readFromIntent(intent)
if (NfcAdapter.ACTION_TAG_DISCOVERED == intent.action) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
}
}
public override fun onPause() {
super.onPause()
disableForegroundDispatch()
}
public override fun onResume() {
super.onResume()
enableForegroundDispatch()
}
/**
* enable foreground dispatch to prevent intent-filter to launch the app again
*/
private fun enableForegroundDispatch() {
nfcAdapter!!.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null)
}
/**
* disable foreground dispatch to allow intent-filter to launch the app
*/
private fun disableForegroundDispatch() {
nfcAdapter!!.disableForegroundDispatch(this)
}
}
7. Find a NFC tag contain text messages, install the app on an android phone, place the back of the android phone over the NFC tag, the phone should vibrate and launches the app. If there is any message on the NFC tag, it should be displayed on the screen.
Search within Codexpedia
Search the entire web