Implement reading payload from NfcA tags, replace intent/characteristic value with that

This commit is contained in:
Kumi 2024-01-11 10:14:42 +01:00
parent 60d6865ede
commit dcdbb3a275

View file

@ -17,6 +17,8 @@ import android.content.pm.PackageManager
import android.nfc.NfcAdapter
import android.nfc.NfcManager
import android.nfc.Tag
import android.nfc.TagLostException
import android.nfc.tech.NfcA
import android.os.Bundle
import android.os.ParcelUuid
import android.util.Log
@ -35,6 +37,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.app.ActivityCompat
import systems.kumi.simplerfiddemo.ui.theme.SimpleRFIDDemoTheme
import java.io.IOException
import java.nio.charset.StandardCharsets
import java.util.UUID
@ -61,6 +65,26 @@ class MainActivity : ComponentActivity() {
val manager = getSystemService(Context.NFC_SERVICE) as NfcManager;
nfcAdapter = manager.defaultAdapter;
// Get required permissions
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_ADVERTISE,
Manifest.permission.NFC),
1
)
}
if (nfcAdapter != null && nfcAdapter.isEnabled) {
// NFC is available
@ -80,7 +104,7 @@ class MainActivity : ComponentActivity() {
) {
Column(modifier = Modifier.padding(16.dp)) {
Status()
Button(onClick = { emitIntent("sample-id") }) {
Button(onClick = { emitIntent("sample-id", "sample-content") }) {
Text(text = "Emit sample Intent")
}
}
@ -224,45 +248,72 @@ class MainActivity : ComponentActivity() {
return String(hexChars)
}
fun emitIntent(id: String) {
@SuppressLint("MissingPermission")
fun emitIntent(id: String, content: String? = null) {
Log.i("BLE", "Setting characteristic and emitting intent: $id")
characteristic.value = id.toByteArray(Charsets.UTF_8)
synchronized(connectedDevices) {
for (device in connectedDevices) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_ADVERTISE
),
1
)
return
if (content != null) {
characteristic.value = content.toByteArray(Charsets.UTF_8)
synchronized(connectedDevices) {
for (device in connectedDevices) {
gattServer.notifyCharacteristicChanged(device, characteristic, false)
}
gattServer.notifyCharacteristicChanged(device, characteristic, false)
}
val intent = Intent("systems.kumi.simplerfiddemo.NEW_TAG")
intent.putExtra("data", content)
sendBroadcast(intent)
}
}
fun readFromTag(tag: Tag): String? {
NfcA.get(tag)?.use { nfcA ->
try {
nfcA.connect()
val bufferSize = 256
val result = ByteArray(bufferSize)
for (block in 4 until 4 + (bufferSize / 4)) {
val command = byteArrayOf(0x30, block.toByte()) // READ command 0x30 for ISO/IEC 14443, and block number
val response = nfcA.transceive(command)
val index = (block - 4) * 4
if (index < result.size) {
val length = Math.min(response.size, result.size - index)
System.arraycopy(response, 0, result, index, length)
}
if (response.indexOf(0x00) != -1) {
break
}
}
// Assuming the data is encoded in UTF-8 and zero terminated
val dataString = result.toString(StandardCharsets.UTF_8).split("\u0000")[0]
return dataString
} catch (e: IOException) {
Log.e("NFC", "IOException while reading tag", e)
} catch (e: TagLostException) {
Log.e("NFC", "TagLostException while reading tag", e)
}
}
val intent = Intent("systems.kumi.simplerfiddemo.NEW_TAG")
intent.putExtra("data", id)
sendBroadcast(intent)
return null
}
@SuppressLint("MissingPermission")
fun onNewTag(tag: Tag) {
val tag_id = toHexString(tag.id)
Log.d("NFC", "New tag detected: ${tag_id}")
emitIntent(tag_id)
val tag_content = readFromTag(tag)
Log.d("NFC", "Tag content: ${tag_content}")
emitIntent(tag_id, tag_content)
setContent() {
SimpleRFIDDemoTheme {
@ -271,9 +322,9 @@ class MainActivity : ComponentActivity() {
color = MaterialTheme.colorScheme.background
) {
Column(modifier = Modifier.padding(16.dp)) {
Status(tag_id)
Button(onClick = { emitIntent("sample-id") }) {
Text(text = "Emit sample Intent")
Status(tag_id, tag_content)
Button(onClick = { emitIntent(tag_id, tag_content) }) {
Text(text = "Emit Intent")
}
}
}
@ -283,9 +334,9 @@ class MainActivity : ComponentActivity() {
}
@Composable
fun Status(id: String? = null) {
fun Status(id: String? = null, content: String? = null) {
Text(
text = "Status: ${if (id != null) "Tag detected: $id" else "Waiting for tag..."}",
text = "Status: ${if (id != null) "Tag detected.\nID: $id\nContent: $content" else "Waiting for tag..."}",
modifier = Modifier
)
}