Implement reading payload from NfcA tags, replace intent/characteristic value with that
This commit is contained in:
parent
60d6865ede
commit
dcdbb3a275
1 changed files with 84 additions and 33 deletions
|
@ -17,6 +17,8 @@ import android.content.pm.PackageManager
|
||||||
import android.nfc.NfcAdapter
|
import android.nfc.NfcAdapter
|
||||||
import android.nfc.NfcManager
|
import android.nfc.NfcManager
|
||||||
import android.nfc.Tag
|
import android.nfc.Tag
|
||||||
|
import android.nfc.TagLostException
|
||||||
|
import android.nfc.tech.NfcA
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.ParcelUuid
|
import android.os.ParcelUuid
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
@ -35,6 +37,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import systems.kumi.simplerfiddemo.ui.theme.SimpleRFIDDemoTheme
|
import systems.kumi.simplerfiddemo.ui.theme.SimpleRFIDDemoTheme
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +65,26 @@ class MainActivity : ComponentActivity() {
|
||||||
val manager = getSystemService(Context.NFC_SERVICE) as NfcManager;
|
val manager = getSystemService(Context.NFC_SERVICE) as NfcManager;
|
||||||
nfcAdapter = manager.defaultAdapter;
|
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) {
|
if (nfcAdapter != null && nfcAdapter.isEnabled) {
|
||||||
|
|
||||||
// NFC is available
|
// NFC is available
|
||||||
|
@ -80,7 +104,7 @@ class MainActivity : ComponentActivity() {
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
Status()
|
Status()
|
||||||
Button(onClick = { emitIntent("sample-id") }) {
|
Button(onClick = { emitIntent("sample-id", "sample-content") }) {
|
||||||
Text(text = "Emit sample Intent")
|
Text(text = "Emit sample Intent")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,45 +248,72 @@ class MainActivity : ComponentActivity() {
|
||||||
return String(hexChars)
|
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")
|
Log.i("BLE", "Setting characteristic and emitting intent: $id")
|
||||||
|
|
||||||
characteristic.value = id.toByteArray(Charsets.UTF_8)
|
if (content != null) {
|
||||||
synchronized(connectedDevices) {
|
characteristic.value = content.toByteArray(Charsets.UTF_8)
|
||||||
for (device in connectedDevices) {
|
synchronized(connectedDevices) {
|
||||||
if (ActivityCompat.checkSelfPermission(
|
for (device in connectedDevices) {
|
||||||
this,
|
gattServer.notifyCharacteristicChanged(device, characteristic, false)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
val intent = Intent("systems.kumi.simplerfiddemo.NEW_TAG")
|
|
||||||
intent.putExtra("data", id)
|
|
||||||
sendBroadcast(intent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
fun onNewTag(tag: Tag) {
|
fun onNewTag(tag: Tag) {
|
||||||
val tag_id = toHexString(tag.id)
|
val tag_id = toHexString(tag.id)
|
||||||
Log.d("NFC", "New tag detected: ${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() {
|
setContent() {
|
||||||
SimpleRFIDDemoTheme {
|
SimpleRFIDDemoTheme {
|
||||||
|
@ -271,9 +322,9 @@ class MainActivity : ComponentActivity() {
|
||||||
color = MaterialTheme.colorScheme.background
|
color = MaterialTheme.colorScheme.background
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
Status(tag_id)
|
Status(tag_id, tag_content)
|
||||||
Button(onClick = { emitIntent("sample-id") }) {
|
Button(onClick = { emitIntent(tag_id, tag_content) }) {
|
||||||
Text(text = "Emit sample Intent")
|
Text(text = "Emit Intent")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,9 +334,9 @@ class MainActivity : ComponentActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Status(id: String? = null) {
|
fun Status(id: String? = null, content: String? = null) {
|
||||||
Text(
|
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
|
modifier = Modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue