An easy to use NFC library for Android to read Ndef-Tags in the foreground. It's meant to be used by inexperienced and experienced developers alike as it allows full customization.
Checkout the NfcLib for iOS NfcLib-iOS
repositories {
mavenCentral()
google()
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.Maliotis:NFCLib-Android:${latestVersion}'
}
<uses-permission android:name="android.permission.NFC" />
Don't enable NFC in the foreground in the onCreate
method instead enable it in onResume
or during i.e press of a button
private lateinit var readNFC: ReadNFC
override fun onResume() {
super.onResume()
//...
readNFC = NFCFactory.create<ReadNFC>(this)
readNFC.enableNFCInForeground()
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
//...
if (intent.action == NfcAdapter.ACTION_TECH_DISCOVERED) {
readNFC.connect(intent)
val payload = readNFC.payload()
payload.forEach {
Log.d("TAG", "onNewIntent: $it")
}
}
}
private lateinit var writeNFC: WriteNFC
override fun onResume() {
super.onResume()
//...
writeNFC = NFCFactory.create<WriteNFC>(this)
writeNFC.enableNFCInForeground()
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
//...
if (intent.action == NfcAdapter.ACTION_TECH_DISCOVERED) {
writeNFC.connect(intent)
val succeeded = writeNFC.write("Hello from NfcLib :)")
Log.d("TAG", "onNewIntent: succeeded = $succeeded")
// when in write mode close the connection
writeNFC.close()
}
}
Don't attempt to read directly after a write
operation, remove the tag and read
in the next tag discovery
private lateinit var readNFC: ReadNFC
private lateinit var writeNFC: WriteNFC
private var flagRead = true
override fun onResume() {
super.onResume()
readNFC = NFCFactory.create<ReadNFC>(this)
writeNFC = NFCFactory.create<WriteNFC>(this)
// use only one object to enable nfc in foreground
writeNFC.enableNFCInForeground()
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
//...
if (intent.action == NfcAdapter.ACTION_TECH_DISCOVERED) {
if (flagRead) {
// read from tag
readNFC.connect(intent)
val payload = readNFC.payload()
payload.forEach {
Log.d("TAG", "onNewIntent: $it")
}
} else {
// write to tag
writeNFC.connect(intent)
val succeeded = writeNFC.write("Hello from NfcLib :)")
Log.d("TAG", "onNewIntent: succeeded = $succeeded")
writeNFC.close()
}
}
}
The library allows for full customization by overriding the connectInterface
in each write and read operations from here on you are in full control of the tags and the connections.
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
if (intent.action == NfcAdapter.ACTION_TECH_DISCOVERED) {
// Determine the action
if (writeAction) {
// Handle the connection interface i.e implement behavior for NfcA, MIFARE e.t.c
writeNFC.connectInterface = object: ConnectInterface {
override fun attemptConnect(tag: Tag) {
//TODO("Not yet implemented")
}
}
// Handle the Ndef tag connection
writeNFC.ndefFunction = {
// return the Ndef Tag
}
writeNFC.connect(intent)
writeNFC.nfcTech = NfcTech.NDEF
writeNFC.localeLanguage = Locale.ENGLISH // Change the language
writeNFC.tnf = NdefRecord.TNF_ABSOLUTE_URI // Change the TNF value
writeNFC.utfEncoding = Charsets.UTF_16 // Change the encoding
// Type record is used only in TNF_WELL_KNOWN
writeNFC.typeRecord = NdefRecord.RTD_URI // Change the type record
writeNFC.write("Hello from NFCLib :)")
// Check the write(String) implementation for passing byteArray
//writeNFC.write(/*ByteArray*/)
// Check the write(String) implementation for passing NdefMessage
//writeNFC.write(/*NdefMessage*/)
// In write transaction DON'T forget to close the connection
writeNFC.close()
}
if (readAction) {
// Change the nfc technology
readNFC.nfcTech = NfcTech.NDEF
// Handle the connection interface i.e implement behavior for NfcA, MIFARE e.t.c
readNFC.connectInterface = object: ConnectInterface {
override fun attemptConnect(tag: Tag) {
//TODO("Not yet implemented")
}
}
// Handle the Ndef tag connection and access to the payload
readNFC.ndefFunction = {
// the function requires to return the Ndef message
}
readNFC.connect(intent)
val message = readNFC.message() // return the NdefMessage
val records = readNFC.records() // return the NdefRecords
val payload = readNFC.payload()
payload.forEach {
Log.d("TAG", "onNewIntent: $it")
}
}
}
}
The below example has been taken from the library, use it as a guide
writeNFC.connectInterface = object: ConnectInterface {
override fun attemptConnect(tag: Tag) {
val technologies = tag.techList
val tagTechs = listOf(*technologies)
val nfcTechName = nfcTech.canonicalName
if (tagTechs.contains(nfcTechName) && nfcTech == NfcTech.NDEF) {
tagTechnology = ndefFunction(tag)
} else if (tagTechs.contains(nfcTechName) && nfcTech == NfcTech.NDEF_FORMATTABLE) {
} else if (tagTechs.contains(nfcTechName) && nfcTech == NfcTech.MIFARE_CLASSIC) {
// TODO
} else if (tagTechs.contains(nfcTechName) && nfcTech == NfcTech.MIFARE_ULTRALIGHT) {
// TODO
}
}
}
The below example has been taken from the library, use it as a guide
readNFC.connectInterface = object: ConnectInterface {
override fun attemptConnect(tag: Tag) {
val technologies = tag.techList
val tagTechs = listOf(*technologies)
val nfcTechName = nfcTech.canonicalName
if (tagTechs.contains(nfcTechName) && nfcTech == NDEF) {
ndefMessage = ndefFunction(tag)
} else if (tagTechs.contains(nfcTechName) && nfcTech == NFCA) {
nfcAFunction(tag)
} else if (tagTechs.contains(nfcTechName) && nfcTech == NFCB) {
// TODO
} else if (tagTechs.contains(nfcTechName) && nfcTech == NFCV) {
// TODO
} else if (tagTechs.contains(nfcTechName) && nfcTech == NFCF) {
// TODO
} else if (tagTechs.contains(nfcTechName) && nfcTech == MIFARE_CLASSIC) {
// TODO
} else if (tagTechs.contains(nfcTechName) && nfcTech == MIFARE_ULTRALIGHT) {
// TODO
}
}
}
The below example has been taken from the library, use it as a guide
readNFC.ndefFunction = { tag ->
val ndefTag = Ndef.get(tag)
var ndefMessage: NdefMessage? = null
ndefTag.let {
it.connect()
ndefMessage = it.cachedNdefMessage
it.close()
}
if (ndefMessage == null) throw RuntimeException("Couldn't connect to nfc tag\n" +
"Ndef Message is null\n" +
"Exiting..")
ndefMessage!!
}
The below example has been taken from the library, use it as a guide
writeNFC.ndefFunction = {
val tagTechnology = Ndef.get(it)
tagTechnology.connect()
tagTechnology
}