Skip to content

Commit

Permalink
Display tag information
Browse files Browse the repository at this point in the history
  • Loading branch information
andras-adam committed Oct 13, 2022
1 parent 2bc7098 commit d0b78a6
Show file tree
Hide file tree
Showing 11 changed files with 232 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.virtualtag.app.data
import android.nfc.tech.MifareClassic
import android.nfc.tech.NfcA
import android.util.Log
import com.virtualtag.app.utils.toHex
import java.io.IOException

class MifareClassicInfo(tag: MifareClassic) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.virtualtag.app.data
import android.nfc.tech.MifareUltralight
import android.nfc.tech.NfcA
import android.util.Log
import com.virtualtag.app.utils.toHex
import java.io.IOException

class MifareUltralightInfo(tag: MifareUltralight) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

// Byte array to HEX helper
fun ByteArray.toHex(): String = joinToString(separator = "") { "%02x".format(it) }
import com.virtualtag.app.utils.toHex

class ScanningViewModel : ViewModel() {
// Currently scanned tag, mifare classic and ultralight information
Expand Down
52 changes: 52 additions & 0 deletions app/src/main/java/com/virtualtag/app/ui/components/DataRow.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.virtualtag.app.ui.components

import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.virtualtag.app.R

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun DataRow(title: String, content: String, icon: ImageVector) {
val context = LocalContext.current
val clipboardManager: ClipboardManager = LocalClipboardManager.current
Column(modifier = Modifier
.fillMaxWidth()
.combinedClickable(
onLongClick = {
clipboardManager.setText(AnnotatedString(content))
Toast
.makeText(context, context.getString(R.string.clipboard), Toast.LENGTH_SHORT)
.show()
},
onClick = { /* do nothing */ })) {
Row(modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp)) {
Icon(icon, contentDescription = null, modifier = Modifier
.size(48.dp)
.padding(horizontal = 4.dp))
Column(modifier = Modifier
.fillMaxWidth()
.padding(top = 2.dp, end = 16.dp)) {
Text(title, fontWeight = FontWeight.Bold, modifier = Modifier.padding(bottom = 4.dp))
Text(content, modifier = Modifier.padding(bottom = 8.dp))
}
}
Divider(color = Color.LightGray)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.virtualtag.app.ui.components

import android.nfc.tech.MifareClassic
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.virtualtag.app.db.Card
import com.virtualtag.app.utils.formatHex

@Composable
fun MifareClassicView(card: Card) {
val id = formatHex(card.id)
val techList = card.techList
.replace("android.nfc.tech.", "")
.replace(",", ", ")
val type = when (card.mifareClassicType ?: MifareClassic.TYPE_UNKNOWN) {
MifareClassic.TYPE_CLASSIC -> "Classic"
MifareClassic.TYPE_PLUS -> "Plus"
MifareClassic.TYPE_PRO -> "Pro"
else -> "Unknown"
}
val sectorCount = card.mifareClassicSectorCount ?: 0
val blockCount = card.mifareClassicBlockCount ?: 0
val size = (card.mifareClassicSize ?: 0) * MifareClassic.BLOCK_SIZE
val timeout = card.mifareClassicTimeout ?: 0
val maxTranscieveLength = card.mifareClassicMaxTransceiveLength ?: 0
val atqa = card.mifareClassicAtqa ?: ""
val sak = card.mifareClassicSak ?: 0
val data = card.mifareClassicData ?: ""

LazyColumn(modifier = Modifier.fillMaxWidth()) {
item {
DataRow(title = "Serial number", content = id, icon = Icons.Filled.Key)
}
item {
DataRow(title = "NFC technologies", content = techList, icon = Icons.Filled.Style)
}
item {
DataRow(title = "MifareClassic type", content = type, icon = Icons.Filled.Category)
}
item {
DataRow(title = "Memory size", content = "$size bytes", icon = Icons.Filled.Save)
}
item {
DataRow(title = "Memory sector count", content = "$sectorCount", icon = Icons.Filled.Save)
}
item {
DataRow(title = "Memory block count", content = "$blockCount", icon = Icons.Filled.Save)
}
item {
DataRow(title = "Transcieve timeout", content = "$timeout ms", icon = Icons.Filled.Sensors)
}
item {
DataRow(title = "Transcieve max length", content = "$maxTranscieveLength bytes", icon = Icons.Filled.Sensors)
}
item {
DataRow(title = "ATQA", content = atqa, icon = Icons.Filled.Code)
}
item {
DataRow(title = "SAK", content = "$sak", icon = Icons.Filled.Code)
}
if (data.isNotEmpty()) {
items(blockCount) { index ->
DataRow(
title = "Memory block ${index + 1}",
content = formatHex(data.substring(index * 32, index * 32 + 32)),
icon = Icons.Filled.Memory
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.virtualtag.app.ui.components

import android.nfc.tech.MifareUltralight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.virtualtag.app.db.Card
import com.virtualtag.app.utils.formatHex

@Composable
fun MifareUltralightView(card: Card) {
val id = formatHex(card.id)
val techList = card.techList
.replace("android.nfc.tech.", "")
.replace(",", ", ")
val type = when (card.mifareUltralightType ?: MifareUltralight.TYPE_UNKNOWN) {
MifareUltralight.TYPE_ULTRALIGHT -> "Ultralight"
MifareUltralight.TYPE_ULTRALIGHT_C -> "Ultralight C"
else -> "Unknown"
}
val size = when (card.mifareUltralightType ?: MifareUltralight.TYPE_UNKNOWN) {
MifareUltralight.TYPE_ULTRALIGHT -> 16 * MifareUltralight.PAGE_SIZE
MifareUltralight.TYPE_ULTRALIGHT_C -> 48 * MifareUltralight.PAGE_SIZE
else -> 0
}
val timeout = card.mifareUltralightTimeout ?: 0
val maxTranscieveLength = card.mifareUltralightMaxTransceiveLength ?: 0
val atqa = card.mifareUltralightAtqa ?: ""
val sak = card.mifareUltralightSak ?: 0
val data = card.mifareUltralightData ?: ""

LazyColumn(modifier = Modifier.fillMaxWidth()) {
item {
DataRow(title = "Serial number", content = id, icon = Icons.Filled.Key)
}
item {
DataRow(title = "NFC technologies", content = techList, icon = Icons.Filled.Style)
}
item {
DataRow(title = "MifareUltralight type", content = type, icon = Icons.Filled.Category)
}
item {
DataRow(title = "Memory size", content = "$size bytes", icon = Icons.Filled.Save)
}
item {
DataRow(title = "Transcieve timeout", content = "$timeout ms", icon = Icons.Filled.Sensors)
}
item {
DataRow(title = "Transcieve max length", content = "$maxTranscieveLength bytes", icon = Icons.Filled.Sensors)
}
item {
DataRow(title = "ATQA", content = atqa, icon = Icons.Filled.Code)
}
item {
DataRow(title = "SAK", content = "$sak", icon = Icons.Filled.Code)
}
// if (data.isNotEmpty()) {
// items(blockCount) { index ->
// DataRow(
// title = "Memory block ${index + 1}",
// content = formatHex(data.substring(index * 32, index * 32 + 32)),
// icon = Icons.Filled.Memory
// )
// }
// }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import com.virtualtag.app.R
import com.virtualtag.app.data.ScanningViewModel
import com.virtualtag.app.data.toHex
import com.virtualtag.app.db.Card
import com.virtualtag.app.ui.components.CardContainer
import com.virtualtag.app.ui.components.ColorButton
import com.virtualtag.app.ui.components.PrimaryButton
import com.virtualtag.app.ui.components.SecondaryButton
import com.virtualtag.app.ui.theme.cardBackGroundColors
import com.virtualtag.app.utils.colorToString
import com.virtualtag.app.utils.toHex
import com.virtualtag.app.viewmodels.CardViewModel

@Composable
Expand Down
26 changes: 15 additions & 11 deletions app/src/main/java/com/virtualtag/app/ui/screens/CardScreen.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package com.virtualtag.app.ui.screens

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import android.nfc.tech.MifareClassic
import android.nfc.tech.MifareUltralight
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.MaterialTheme.colors
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.virtualtag.app.db.Card
import com.virtualtag.app.ui.components.MifareClassicView
import com.virtualtag.app.ui.components.MifareUltralightView
import com.virtualtag.app.viewmodels.CardViewModel

@Composable
Expand All @@ -22,13 +22,11 @@ fun CardScreen(
editCard: (id: String) -> Unit,
goBack: () -> Unit
) {
val card =
model.getCardById(id)
.observeAsState(Card(id = "0", name = "Unknown card", color = "#fff8f8f8"))
val card = model.getCardById(id).observeAsState(null)
Scaffold(
topBar = {
TopAppBar(
title = { Text(card.value.name) },
title = { Text(card.value?.name ?: "") },
navigationIcon = {
IconButton(onClick = goBack) {
Icon(
Expand All @@ -47,7 +45,13 @@ fun CardScreen(
.padding(8.dp), color = colors.background
) {
Column(modifier = Modifier.fillMaxWidth()) {
Text("Card details - placeholder")
if (card.value == null) {
// Loading
} else if (card.value?.techList?.contains(MifareClassic::class.java.name) == true) {
MifareClassicView(card = card.value!!)
} else if (card.value?.techList?.contains(MifareUltralight::class.java.name) == true) {
MifareUltralightView(card = card.value!!)
}
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/virtualtag/app/utils/HexUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.virtualtag.app.utils

// Byte array to HEX helper
fun ByteArray.toHex(): String = joinToString(separator = "") { "%02x".format(it) }

// Format HEX strings into colon (:) delimited HEX strings
// E.g.: BF55 -> BF:55
fun formatHex(content: String): String {
val result = arrayListOf<String>()
for (i in content.indices step 2) {
result.add(content.substring(i, i + 2))
}
return result.joinToString(":")
}
1 change: 1 addition & 0 deletions app/src/main/res/values-hu/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
<string name="scan_description">Tartsd az eszközt az NFC olvasóhoz a beolvasáshoz</string>
<string name="nfc_sensor_error">NFC érzékelő hiba</string>
<string name="nfc_sensor_error_description">Úgy tűnik, hogy a készüléked nem rendelkezik NFC érzékelővel. Sajnos ezzel az eszközzel nem lehet NFC kártyákat beolvasni.</string>
<string name="clipboard">Vágólapra másolva!</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
<string name="scan_description">Hold your device near your NFC tag to scan</string>
<string name="nfc_sensor_error">NFC sensor error</string>
<string name="nfc_sensor_error_description">It seems like your device does not have an NFC sensor. Unfortunately, you can\'t scan NFC cards with this device.</string>
<string name="clipboard">Copied to clipboard!</string>
</resources>

0 comments on commit d0b78a6

Please sign in to comment.