Skip to content

Commit

Permalink
Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
guillermovogel committed Jul 26, 2023
1 parent 9519969 commit 070dcb6
Show file tree
Hide file tree
Showing 10 changed files with 34 additions and 65 deletions.
11 changes: 6 additions & 5 deletions app/src/main/java/com/vogel/nfc_reader/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
Expand All @@ -17,10 +19,8 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.lifecycleScope
import com.vogel.nfc_reader.ui.theme.NFCReaderTheme
import dagger.hilt.android.AndroidEntryPoint

Expand All @@ -40,7 +40,7 @@ class MainActivity : ComponentActivity() {

override fun onPause() {
super.onPause()
viewModel.cardReaderListener.stop(this)
viewModel.cardReaderListener.stopReading(this)
}

}
Expand All @@ -54,13 +54,14 @@ fun CardDataScreen(
val context = LocalContext.current

LaunchedEffect(Unit) {
viewModel.cardReaderListener.start(context as MainActivity)
viewModel.cardReaderListener.startReading(context as MainActivity)
}

Column(
modifier = Modifier
.background(MaterialTheme.colors.background)
.fillMaxSize(),
.fillMaxSize()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/com/vogel/nfc_reader/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vogel.nfc_reader.nfc.api.CardReader
import com.vogel.nfc_reader.nfc.api.CardReaderListener
import com.vogel.nfc_reader.nfc.model.CardData
import com.vogel.nfc_reader.nfc.model.Card
import com.vogel.nfc_reader.nfc.utils.NFCState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
Expand All @@ -35,7 +35,7 @@ class MainViewModel @Inject constructor() : ViewModel() {
uiState = uiState.copy(
cardStateText = when (it) {
NFCState.CardLost -> "Keep it steady, card lost!"
is NFCState.Error -> CardData.fetchErrorInformation(it.throwable)
is NFCState.Error -> Card.fetchErrorInformation(it.throwable)
NFCState.Disabled -> {
uiState = uiState.copy(settingsButtonVisible = true)
"NFC is disabled. Go to settings to activate it"
Expand All @@ -44,7 +44,7 @@ class MainViewModel @Inject constructor() : ViewModel() {
NFCState.NotSupported -> "NFC is not supported in this device"
NFCState.ReadyToScan -> "The device is ready to scan"
NFCState.StartReading -> "The device is reading the card..."
is NFCState.Success -> CardData.fetchCardInformation(it.card)
is NFCState.Success -> Card.fetchCardInformation(it.card)
}
)
}
Expand Down
18 changes: 3 additions & 15 deletions nfc_reader/src/main/java/com/vogel/nfc_reader/nfc/Extentions.kt
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
package com.vogel.nfc_reader.nfc

import com.vogel.nfc_reader.nfc.model.CardData
import com.github.devnied.emvnfccard.enums.EmvCardScheme
import com.github.devnied.emvnfccard.model.EmvCard
import com.github.devnied.emvnfccard.model.enums.CardStateEnum
import com.vogel.nfc_reader.nfc.model.Card
import com.vogel.nfc_reader.nfc.model.CardState

internal fun ByteArray.toHex(space: Boolean = false): String =
joinToString(separator = if (space) " " else "") { "%02x".format(it) }.uppercase()

internal fun EmvCard.mapToCardData(): CardData {
val aids = applications.map { it.aid.toHex() }
val types = aids.map { EmvCardScheme.getCardTypeByAid(it).name }

return CardData(
aids = aids,
types = types,
internal fun EmvCard.mapToCard(): Card =
Card(
expireDate = expireDate,
number = cardNumber,
state = when (state) {
null, CardStateEnum.UNKNOWN -> CardState.UNKNOWN
CardStateEnum.LOCKED -> CardState.LOCKED
CardStateEnum.ACTIVE -> CardState.ACTIVE
},
holderFirstName = holderFirstname,
holderLastName = holderLastname,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ package com.vogel.nfc_reader.nfc.api
import android.content.Context
import android.nfc.tech.IsoDep
import com.github.devnied.emvnfccard.parser.EmvTemplate
import com.vogel.nfc_reader.nfc.model.CardData
import com.vogel.nfc_reader.nfc.provider.TransceiverProvider
import com.vogel.nfc_reader.nfc.model.Card
import com.vogel.nfc_reader.nfc.implementations.ReaderImplementation

interface CardReader {
fun getCardResult(isoDep: IsoDep): Result<CardData>
fun getCardResult(isoDep: IsoDep): Result<Card>
fun openSettings(context: Context) {}

companion object {
Expand All @@ -24,7 +23,6 @@ interface CardReader {
return ReaderImplementation(
config = config,
builder = EmvTemplate.Builder(),
provider = TransceiverProvider()
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import kotlinx.coroutines.flow.Flow
interface CardReaderListener {
val nfcStatus: Flow<NFCState>

fun start(activity: Activity)
fun stop(activity: Activity)
fun openSettings(context: Context){}
fun startReading(activity: Activity)
fun stopReading(activity: Activity)
fun openSettings(context: Context) {}

companion object {
fun newInstance(cardReader: CardReader): CardReaderListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ListenerImplementation constructor(
* If enabled, then reader mode is activated so that the user can
* scan their NFC card (debit/credit).
*/
override fun start(activity: Activity) {
override fun startReading(activity: Activity) {
adapter = NFCUtils.getNfcAdapter(activity)?.apply {
// NFC Supported
if (!isEnabled) {
Expand Down Expand Up @@ -68,7 +68,7 @@ class ListenerImplementation constructor(
/**
* This function stops the NFC reader from scanning for NFC cards.
*/
override fun stop(activity: Activity) {
override fun stopReading(activity: Activity) {
adapter?.disableReaderMode(activity)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,27 @@ import android.content.Context
import android.nfc.tech.IsoDep
import com.github.devnied.emvnfccard.parser.EmvTemplate
import com.vogel.nfc_reader.nfc.api.CardReader
import com.vogel.nfc_reader.nfc.mapToCardData
import com.vogel.nfc_reader.nfc.model.CardData
import com.vogel.nfc_reader.nfc.model.CardState
import com.vogel.nfc_reader.nfc.provider.TransceiverProvider
import com.vogel.nfc_reader.nfc.mapToCard
import com.vogel.nfc_reader.nfc.model.Card
import com.vogel.nfc_reader.nfc.provider.Provider
import com.vogel.nfc_reader.nfc.utils.ACTION_NFC_SETTINGS

class ReaderImplementation constructor(
private val builder: EmvTemplate.Builder,
private val config: EmvTemplate.Config,
private val provider: TransceiverProvider,
) : CardReader {

/**
* Get card data from NFC card, and map it to [CardData]
* Get card data from NFC card, and map it to [Card]
*/
override fun getCardResult(isoDep: IsoDep): Result<CardData> {
override fun getCardResult(isoDep: IsoDep): Result<Card> {
return runCatching {
isoDep.connect()
builder.setConfig(config)
.setProvider(provider.getTransceiver(isoDep))
.setProvider(Provider(isoDep))
.build()
.readEmvCard()
.mapToCardData()
.mapToCard()
}
.also {
runCatching { isoDep.close() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@ import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

class CardData(
val aids: List<String>,
val types: List<String>,
data class Card(
val expireDate: Date?,
val number: String?,
val state: CardState,
val holderFirstName: String? = "First name not found",
val holderLastName: String? = "Lastname not found",
) {

var formattedNumber: String? = null
Expand Down Expand Up @@ -45,17 +41,13 @@ class CardData(
companion object {
internal val EXPECTED_DATE_FORMAT = SimpleDateFormat("MM/yy", Locale.US)

fun fetchCardInformation(cardData: CardData): String = """
AID: ${cardData.aids.joinToString(" | ")}
Type: ${cardData.types.joinToString(" | ")}
State: ${cardData.state}
fun fetchCardInformation(card: Card): String = """
State: ${card.state}
Number: ${cardData.formattedNumber}
Expires: ${cardData.formattedDate}
Number: ${card.formattedNumber}
Expires: ${card.formattedDate}
Valid: ${cardData.isValid}
Holder: ${cardData.holderLastName}
Valid: ${card.isValid}
""".trimIndent()

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import android.content.Intent
import android.nfc.NfcAdapter
import android.nfc.NfcManager
import android.provider.Settings
import com.vogel.nfc_reader.nfc.model.CardData
import com.vogel.nfc_reader.nfc.model.Card


object NFCUtils {
Expand Down Expand Up @@ -37,7 +37,7 @@ sealed class NFCState {
object Disabled : NFCState()
object NotSupported : NFCState()
data class Error(val throwable: Throwable) : NFCState()
data class Success(val card: CardData) : NFCState()
data class Success(val card: Card) : NFCState()
}

val ACTION_NFC_SETTINGS = Intent(Settings.ACTION_NFC_SETTINGS)

0 comments on commit 070dcb6

Please sign in to comment.