Implement emulation (hopefully!)

This commit is contained in:
Kodi Craft 2025-08-25 18:53:18 +02:00
parent 6481878cee
commit de97b9b7e1
Signed by: kodi
GPG Key ID: 69D9EED60B242822
2 changed files with 37 additions and 12 deletions

View File

@ -50,6 +50,7 @@ import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
@ -83,7 +84,7 @@ class MainActivity : ComponentActivity() {
lateinit var adapter: NfcAdapter
var canEmulateCard: Boolean = false
var emulationActive: Boolean = false
var emulationCardID: String? = null
private val TAG = "AimeReader"
private val FILENAME = "cards.json"
@ -158,7 +159,16 @@ class MainActivity : ComponentActivity() {
val scope = rememberCoroutineScope()
var snackbarHostState = remember { SnackbarHostState() }
var selectedCardIndexForEmulation by rememberSaveable { mutableStateOf(-1) }
var selectedCardIndexForEmulation by rememberSaveable { mutableIntStateOf(-1) }
LaunchedEffect(selectedCardIndexForEmulation) {
if (selectedCardIndexForEmulation == -1) {
this@MainActivity.emulationCardID = null
} else {
this@MainActivity.emulationCardID = cards[selectedCardIndexForEmulation].getHexID()
}
updateEmulation()
}
AimeReaderTheme {
Scaffold (
@ -261,17 +271,28 @@ class MainActivity : ComponentActivity() {
adapter.disableForegroundDispatch(this)
val nfcfCardEmulation = NfcFCardEmulation.getInstance(adapter)
nfcfCardEmulation.disableService(this)
Log.i(TAG, "Pausing activity, emulation disabled")
}
public override fun onResume() {
super.onResume()
adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)
val nfcfCardEmulation = NfcFCardEmulation.getInstance(adapter)
nfcfCardEmulation.registerSystemCodeForService(ComponentName(this, AimeHostApduService::class.java), "4000")
Log.d(TAG, nfcfCardEmulation.setNfcid2ForService(ComponentName(this, AimeHostApduService::class.java), "02FE000000000000").toString())
Log.d(TAG, nfcfCardEmulation.enableService(this, ComponentName(this, AimeHostApduService::class.java)).toString())
Log.i(TAG, "activity resumed")
updateEmulation()
}
fun updateEmulation() {
val nfcfCardEmulation = NfcFCardEmulation.getInstance(adapter)
if (emulationCardID != null) {
Log.i(TAG, "Enabling emulation of card $emulationCardID")
nfcfCardEmulation.registerSystemCodeForService(ComponentName(this, AimeHostApduService::class.java), "4000")
Log.d(TAG, nfcfCardEmulation.setNfcid2ForService(ComponentName(this, AimeHostApduService::class.java), emulationCardID).toString())
Log.d(TAG, nfcfCardEmulation.enableService(this, ComponentName(this, AimeHostApduService::class.java)).toString())
} else {
Log.i(TAG, "Disabling card emulation")
nfcfCardEmulation.disableService(this)
}
}
}
@Composable
@ -288,7 +309,7 @@ fun CardList(
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
modifier = modifier
.fillMaxSize()
.padding(innerPadding)
) {
@ -297,7 +318,7 @@ fun CardList(
}
} else {
LazyColumn (
modifier = Modifier
modifier = modifier
.fillMaxWidth()
.padding(innerPadding)
) {
@ -327,7 +348,7 @@ fun CardDisplay(
val coroutineScope = rememberCoroutineScope()
Row (
modifier = Modifier
modifier = modifier
.padding(horizontal = 8.dp, vertical = 8.dp)
.fillMaxWidth()
.clip(shape = RoundedCornerShape(16.dp))
@ -383,7 +404,7 @@ fun CardDisplay(
@Preview
@Composable
fun CardDisplayPreview(modifier: Modifier = Modifier) {
Column(modifier = Modifier.fillMaxSize()) {
Column(modifier = modifier.fillMaxSize()) {
CardDisplay(SavedCard(byteArrayOf(0x02, 0xFE.toByte(), 0x02, 0x03, 0x04, 0x05, 0x06, 0x07)), true, true, {}, {}, {})
CardDisplay(SavedCard(byteArrayOf(0x02, 0xFE.toByte(), 0x12, 0x34, 0x56, 0x78, 0x12, 0x34)), true, false, {}, {}, {})
CardDisplay(SavedCard(byteArrayOf(0x02, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07)), true, false, {}, {}, {})

View File

@ -1,6 +1,5 @@
package me.kdcf.aimereader
import android.os.Parcel
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable
@ -25,6 +24,11 @@ class SavedCard(private var code: ByteArray, private var friendlyName: String =
return getPadded().chunked(4).joinToString(" ")
}
@OptIn(ExperimentalStdlibApi::class)
fun getHexID(): String {
return getCode().toHexString()
}
fun getDisplay(): String {
if (friendlyName.isEmpty()) {
return getSpaced()