I am trying to guarantee that my Android application will not crash when I try to write to an NFC tag. The edge case I am working on is: What if I try to write but there is nothing to write to?
I created this write() method, which checks the NFC status in checkNFCStatus()... It prevents some cases (like when a user had a card against the device but removed it before writing). But it does not prevent the case when the user never had a tag to begin with.
@Throws(IOException::class, FormatException::class)
fun write(text: String, tag: Tag?, context: Context): Boolean {
val records = arrayOf(createRecord(text))
val message = NdefMessage(records)
**val ndef = Ndef.get(tag)**
if (checkNFCStatus(tag)) {
ndef.connect()
val ndefMessage = ndef.ndefMessage
Log.d(TAG, "ndef is : " ndef.type)
Log.d(TAG, "ndef message is : $ndefMessage")
if (ndef.isWritable) {
Log.d("MAIN", "NDEF is writable.")
}
if (!ndef.isWritable) {
Log.d("MAIN", "NDEF is read-only.")
}
if (!ndef.isConnected) {
Log.d("MAIN", "NDEF is not connected.")
}
if (ndef.isConnected) {
ndef.writeNdefMessage(message)
ndef.close()
return true
}
ndef.close()
}
DebugUtils().showToast(
context,
"Try repositioning the card/chip. It is not close enough to the device.")
return false
}
private fun checkNFCStatus(myTag: Tag?): Boolean {
try {
if (myTag != null) {
val ndefTag = Ndef.get(myTag)
ndefTag.connect()
return if (ndefTag.isConnected) {
Log.d("network", "NFC connected")
ndefTag.close()
true
} else {
Log.d("network", "NFC disconnected")
false
}
}
} catch (e: IOException) {
e.printStackTrace()
Log.d("network", "NFC disconnected")
}
return false
}
The problematic line of code is: val ndef = Ndef.get(tag) Basically if there never was a tag to begin with, this throws an NPE:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.nfc.Tag.hasTech(int)' on a null object reference
CodePudding user response:
Kotlin has a null safety feature, so whenever you know there is a chance for a variable to be null, you should use safe calls :
val a : Boolean? // now this variable can be null
so replace this :
val ndef = Ndef.get(tag)
with :
val ndef : Boolean? = Ndef.get(tag)
now you will not get this NullPointer error and whenever you want to check the value of ndef you should check it is null or not.
CodePudding user response:
Okay.... so I first went the approach of null safety, but it wasn't working. The answer should have been more obvious.
First check if the tag is null!
if (tag != null) {
var ndef = Ndef.get(tag)
if (checkNFCStatus(tag)) {....}