Skip to content

Commit aa1f415

Browse files
committed
Refined NfcAdapterController to inject NfcControllerFactory internally. This means that NfcViewModel no longer needs the factory class passed in.
1 parent 261a57b commit aa1f415

File tree

14 files changed

+154
-46
lines changed

14 files changed

+154
-46
lines changed

app/build.gradle.kts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ plugins {
77

88
android {
99
namespace = "com.carbidecowboy.intra_example"
10-
compileSdk = 34
10+
compileSdk = 35
1111

1212
defaultConfig {
1313
applicationId = "com.hoker.intra_example"
1414
minSdk = 28
1515
targetSdk = 35
16-
versionCode = 131
17-
versionName = "1.3.1"
16+
versionCode = 133
17+
versionName = "1.3.3"
1818

1919
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2020
vectorDrawables {
@@ -57,6 +57,7 @@ dependencies {
5757

5858
implementation("androidx.appcompat:appcompat:1.6.1")
5959
implementation("com.google.android.material:material:1.12.0")
60+
implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
6061
implementation("androidx.navigation:navigation-compose:2.7.7")
6162
implementation("androidx.compose.ui:ui:1.6.7")
6263
implementation("androidx.compose.material:material:1.6.7")
@@ -68,5 +69,5 @@ dependencies {
6869
implementation("androidx.constraintlayout:constraintlayout-compose-android:1.1.0-alpha13")
6970

7071
implementation(project(":intra"))
71-
implementation("com.github.CarbideCowboy:Supra:0.0.6")
72+
implementation("com.github.h0ker:Supra:0.0.9")
7273
}

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools">
4+
<uses-permission android:name="android.permission.INTERNET"/>
5+
<uses-permission android:name="android.permission.NFC"/>
46

57
<application
68
android:allowBackup="true"

app/src/main/java/com/hoker/intra_example/presentation/IntraExampleActivity.kt

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,69 @@
11
package com.hoker.intra_example.presentation
22

33
import android.os.Bundle
4-
import android.os.PersistableBundle
4+
import android.widget.Toast
55
import androidx.activity.compose.setContent
6-
import androidx.compose.foundation.layout.fillMaxSize
7-
import androidx.compose.material.MaterialTheme
8-
import androidx.compose.material.Surface
6+
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.foundation.layout.padding
8+
import androidx.compose.material.Text
9+
import androidx.compose.runtime.LaunchedEffect
910
import androidx.compose.ui.Modifier
1011
import androidx.compose.ui.graphics.Color
12+
import androidx.compose.ui.platform.LocalContext
13+
import androidx.compose.ui.text.font.FontWeight
14+
import androidx.compose.ui.unit.dp
15+
import androidx.compose.ui.unit.sp
16+
import androidx.hilt.navigation.compose.hiltViewModel
1117
import com.hoker.intra.domain.NfcActivity
12-
import com.carbidecowboy.supra.presentation.scaffolds.SupraGyroScaffold
18+
import com.hoker.supra.presentation.scaffolds.SupraGyroScaffold
1319
import dagger.hilt.android.AndroidEntryPoint
20+
import kotlinx.coroutines.flow.collectLatest
1421

1522
@AndroidEntryPoint
1623
class IntraExampleActivity: NfcActivity() {
1724

1825
override fun onCreate(savedInstanceState: Bundle?) {
1926
super.onCreate(savedInstanceState)
2027
setContent {
28+
29+
val viewModel: IntraExampleViewModel = hiltViewModel()
30+
val context = LocalContext.current
31+
32+
LaunchedEffect(Unit) {
33+
viewModel.errorFlow.collectLatest { errorMessage ->
34+
Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show()
35+
}
36+
}
37+
2138
SupraGyroScaffold(
22-
borderColor = Color.Black,
23-
backgroundColor = Color.DarkGray
39+
borderColor = Color.DarkGray,
40+
backgroundColor = Color.Black
2441
) {
25-
42+
Column(
43+
modifier = Modifier.padding(16.dp)
44+
) {
45+
if (viewModel.jwtText == null) {
46+
Text(
47+
text = "Scan to get JWT",
48+
color = Color.White,
49+
fontSize = 24.sp,
50+
fontWeight = FontWeight.Bold
51+
)
52+
}
53+
viewModel.jwtText?.let { jwt ->
54+
Text(
55+
text = "JWT:",
56+
color = Color.White,
57+
fontSize = 24.sp,
58+
fontWeight = FontWeight.Bold
59+
)
60+
Text(
61+
text = jwt,
62+
color = Color.White,
63+
fontSize = 16.sp
64+
)
65+
}
66+
}
2667
}
2768
}
2869
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.hoker.intra_example.presentation
2+
3+
import android.nfc.Tag
4+
import androidx.compose.runtime.MutableState
5+
import androidx.compose.runtime.mutableStateOf
6+
import androidx.lifecycle.viewModelScope
7+
import com.hoker.intra.domain.NfcAdapterController
8+
import com.hoker.intra.domain.NfcController
9+
import com.hoker.intra.domain.NfcViewModel
10+
import com.hoker.intra.domain.OperationResult
11+
import dagger.hilt.android.lifecycle.HiltViewModel
12+
import kotlinx.coroutines.Dispatchers
13+
import kotlinx.coroutines.channels.Channel
14+
import kotlinx.coroutines.flow.receiveAsFlow
15+
import kotlinx.coroutines.launch
16+
import javax.inject.Inject
17+
18+
@HiltViewModel
19+
class IntraExampleViewModel @Inject constructor(
20+
nfcAdapterController: NfcAdapterController
21+
): NfcViewModel(nfcAdapterController) {
22+
23+
private val _jwtText: MutableState<String?> = mutableStateOf(null)
24+
val jwtText: String?
25+
get() { return _jwtText.value }
26+
27+
private val _errorChannel = Channel<String>(Channel.BUFFERED)
28+
var errorFlow = _errorChannel.receiveAsFlow()
29+
30+
override fun onNfcTagDiscovered(tag: Tag, nfcController: NfcController) {
31+
viewModelScope.launch(Dispatchers.IO) {
32+
nfcController.withConnection(tag) {
33+
when (val result = nfcController.getVivokeyJwt(tag)) {
34+
is OperationResult.Success -> {
35+
_jwtText.value = result.data
36+
}
37+
is OperationResult.Failure -> {
38+
_jwtText.value = null
39+
_errorChannel.trySend(result.exception?.message ?: "Error getting JWT")
40+
}
41+
}
42+
}
43+
}
44+
}
45+
}

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ buildscript {
77
}
88

99
plugins {
10-
id("com.android.application") version "8.4.0" apply false
10+
id("com.android.application") version "8.6.0" apply false
1111
id("org.jetbrains.kotlin.android") version "1.9.24" apply false
12-
id("com.android.library") version "8.4.0" apply false
12+
id("com.android.library") version "8.6.0" apply false
1313
id("com.google.devtools.ksp") version "1.9.10-1.0.13" apply false
1414
}

intra/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ afterEvaluate {
5959
publications {
6060
create<MavenPublication>("release") {
6161
from(components["release"])
62-
groupId = "com.github.CarbideCowboy"
62+
groupId = "com.github.h0ker"
6363
artifactId = "Intra"
64-
version = "1.3.1"
64+
version = "1.3.3"
6565
}
6666
}
6767
}

intra/src/main/java/com/hoker/intra/data/IsodepControllerImpl.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,14 @@ class IsodepControllerImpl @Inject constructor(
139139
command[6] = 0x00.toByte()
140140
command[7] = 0x00.toByte()
141141

142-
val isoDep = IsoDep.get(tag)
143-
isoDep.connect()
144-
145142
//TODO: Add error check on this result
146-
isoDep.transceive(NDEF_SEL)
143+
isoDep?.transceive(NDEF_SEL)
147144

148145
// send part 1 command
149-
val part1Result = isoDep.transceive(command)
146+
val part1Result = isoDep?.transceive(command)
150147

151148
var piccChallenge = part1Result
152-
piccChallenge = piccChallenge.copyOfRange(0, 16)
149+
piccChallenge = piccChallenge?.copyOfRange(0, 16)
153150
println("PICC Challenge:\n${Hex.encodeHexString(piccChallenge)}\n\n")
154151

155152
val challengeRequest = ChallengeRequest(
@@ -179,8 +176,7 @@ class IsodepControllerImpl @Inject constructor(
179176
command[37] = 0x00.toByte()
180177

181178
Log.i("Part 2 Command", Hex.encodeHexString(command))
182-
val response = isoDep.transceive(command)
183-
isoDep.close()
179+
val response = isoDep?.transceive(command)
184180
Log.i("Response", Hex.encodeHexString(response))
185181

186182
val responseString = Hex.encodeHexString(response)
@@ -267,6 +263,10 @@ class IsodepControllerImpl @Inject constructor(
267263
)
268264
}
269265

266+
override fun getMaxTransceiveLength(): Int? {
267+
return isoDep?.maxTransceiveLength
268+
}
269+
270270
override suspend fun writeNdefMessage(tag: Tag, message: NdefMessage): OperationResult<Unit> {
271271
return try {
272272
val ndef = Ndef.get(tag)

intra/src/main/java/com/hoker/intra/data/NfcAControllerImpl.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ class NfcAControllerImpl @Inject constructor(
204204
}
205205
}
206206

207+
override fun getMaxTransceiveLength(): Int? {
208+
return nfcA?.maxTransceiveLength
209+
}
210+
207211
override suspend fun getNdefCapacity(ndef: Ndef): OperationResult<Int> {
208212
return try {
209213
val result = ndef.maxSize

intra/src/main/java/com/hoker/intra/data/NfcVControllerImpl.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,6 @@ class NfcVControllerImpl @Inject constructor(
175175
OperationResult.Failure()
176176
}
177177

178-
val nfcV = NfcV.get(tag)
179-
nfcV.connect()
180-
181178
// truncate challenge to 10 bytes
182179
// challenge string into hex
183180
val challengeBytes: ByteArray =
@@ -199,8 +196,7 @@ class NfcVControllerImpl @Inject constructor(
199196
challengeBytes.copyInto(command, UID_BYTE_LENGTH + 5, 0)
200197
// connect and send command
201198
Log.i("Command", Hex.encodeHexString(command))
202-
val response = nfcV.transceive(command)
203-
nfcV.close()
199+
val response = nfcV?.transceive(command)
204200
Log.i("Response", Hex.encodeHexString(response))
205201

206202
val sessionRequest = SessionRequest(
@@ -231,6 +227,10 @@ class NfcVControllerImpl @Inject constructor(
231227
}
232228
}
233229

230+
override fun getMaxTransceiveLength(): Int? {
231+
return nfcV?.maxTransceiveLength
232+
}
233+
234234
override suspend fun getNdefMessage(ndef: Ndef): OperationResult<NdefMessage?> {
235235
return try {
236236
val result = ndef.cachedNdefMessage

intra/src/main/java/com/hoker/intra/di/NfcModule.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,11 @@ abstract class NfcModule {
5757

5858
@Provides
5959
@Singleton
60-
fun provideNfcAdapterController(nfcAdapter: NfcAdapter?): NfcAdapterController {
61-
return NfcAdapterController(nfcAdapter)
60+
fun provideNfcAdapterController(
61+
nfcAdapter: NfcAdapter?,
62+
nfcControllerFactory: NfcControllerFactory
63+
): NfcAdapterController {
64+
return NfcAdapterController(nfcAdapter, nfcControllerFactory)
6265
}
6366
}
6467

0 commit comments

Comments
 (0)