mirror of
https://github.com/status-im/keycard-connect.git
synced 2025-02-27 10:00:38 +00:00
add tap prompt
This commit is contained in:
parent
fe4af3e5d8
commit
9c1f4fb612
@ -25,12 +25,12 @@ object Registry {
|
||||
lateinit var nfcAdapter: NfcAdapter
|
||||
private set
|
||||
|
||||
fun init(activity: Activity) {
|
||||
fun init(activity: Activity, listener: ScriptListener) {
|
||||
pairingManager = PairingManager(activity)
|
||||
pinCache = PINCache()
|
||||
|
||||
nfcAdapter = NfcAdapter.getDefaultAdapter(activity)
|
||||
scriptExecutor = CardScriptExecutor(activity)
|
||||
scriptExecutor = CardScriptExecutor(activity, listener)
|
||||
|
||||
cardManager = NFCCardManager()
|
||||
cardManager.setCardListener(scriptExecutor)
|
||||
|
@ -6,7 +6,7 @@ import im.status.keycard.applet.KeycardCommandSet
|
||||
import im.status.keycard.io.CardChannel
|
||||
import im.status.keycard.io.CardListener
|
||||
|
||||
class CardScriptExecutor(private val activity: Activity) : CardListener {
|
||||
class CardScriptExecutor(private val activity: Activity, private val listener: ScriptListener) : CardListener {
|
||||
class ScriptContext(val activity: Activity, val cmdSet: KeycardCommandSet)
|
||||
|
||||
enum class State {
|
||||
@ -23,24 +23,25 @@ class CardScriptExecutor(private val activity: Activity) : CardListener {
|
||||
val executionContext = ScriptContext(activity, KeycardCommandSet(channel))
|
||||
|
||||
if (state == State.READY) {
|
||||
state = State.RUNNING
|
||||
startScript()
|
||||
} else if (state == State.UX_ONGOING) {
|
||||
return
|
||||
}
|
||||
|
||||
val runningScript = script ?: defaultScript ?: return
|
||||
|
||||
var success = true
|
||||
|
||||
script@for (cmd in runningScript) {
|
||||
when (cmd.run(executionContext)) {
|
||||
CardCommand.Result.OK -> {}
|
||||
CardCommand.Result.CANCEL -> { break@script}
|
||||
CardCommand.Result.CANCEL -> { success = false; break@script}
|
||||
CardCommand.Result.UX_ONGOING -> { waitingCmd = cmd; return }
|
||||
CardCommand.Result.RETRY -> { return }
|
||||
}
|
||||
}
|
||||
|
||||
script = null
|
||||
state = State.READY
|
||||
finishScript(if (success) CardCommand.Result.OK else CardCommand.Result.CANCEL)
|
||||
}
|
||||
|
||||
override fun onDisconnected() {
|
||||
@ -52,22 +53,30 @@ class CardScriptExecutor(private val activity: Activity) : CardListener {
|
||||
waitingCmd?.onDataReceived(data)
|
||||
state = State.RUNNING
|
||||
} else {
|
||||
script = null
|
||||
state = State.READY
|
||||
cancelScript()
|
||||
}
|
||||
}
|
||||
|
||||
fun runScript(script: List<CardCommand>): Boolean {
|
||||
if (state == State.READY) {
|
||||
this.script = script
|
||||
startScript()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun cancelScript() {
|
||||
fun cancelScript() = finishScript(CardCommand.Result.CANCEL)
|
||||
|
||||
private fun finishScript(result: CardCommand.Result) {
|
||||
script = null
|
||||
state = State.READY
|
||||
listener.onScriptFinished(result)
|
||||
}
|
||||
|
||||
private fun startScript() {
|
||||
state = State.RUNNING
|
||||
listener.onScriptStarted()
|
||||
}
|
||||
}
|
@ -25,16 +25,16 @@ class InitCommand : CardCommand {
|
||||
}
|
||||
|
||||
if (initPIN != null && initPUK != null && initPairing != null) {
|
||||
try {
|
||||
return try {
|
||||
context.cmdSet.init(initPIN, initPUK, initPairing).checkOK()
|
||||
context.cmdSet.select().checkOK()
|
||||
context.cmdSet.autoPair(initPairing)
|
||||
Registry.pairingManager.putPairing(context.cmdSet.applicationInfo.instanceUID, context.cmdSet.pairing)
|
||||
return CardCommand.Result.OK
|
||||
CardCommand.Result.OK
|
||||
} catch (e: IOException) {
|
||||
return CardCommand.Result.RETRY
|
||||
CardCommand.Result.RETRY
|
||||
} catch (e: APDUException) {
|
||||
return CardCommand.Result.CANCEL
|
||||
CardCommand.Result.CANCEL
|
||||
} finally {
|
||||
initPIN = null
|
||||
initPUK = null
|
||||
|
@ -0,0 +1,6 @@
|
||||
package im.status.keycard.connect.card
|
||||
|
||||
interface ScriptListener {
|
||||
fun onScriptStarted()
|
||||
fun onScriptFinished(result: CardCommand.Result)
|
||||
}
|
@ -48,7 +48,7 @@ class InitActivity : AppCompatActivity() {
|
||||
finish()
|
||||
}
|
||||
|
||||
fun randomToken(length: Int): String {
|
||||
private fun randomToken(length: Int): String {
|
||||
return Base64.encodeToString(Crypto.randomBytes(length), NO_PADDING or NO_WRAP)
|
||||
}
|
||||
}
|
||||
|
@ -5,18 +5,28 @@ import android.nfc.NfcAdapter
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.ViewSwitcher
|
||||
import im.status.keycard.connect.R
|
||||
import im.status.keycard.connect.Registry
|
||||
import im.status.keycard.connect.card.*
|
||||
import im.status.keycard.connect.data.REQ_INTERACTIVE_SCRIPT
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
class MainActivity : AppCompatActivity(), ScriptListener {
|
||||
private lateinit var viewSwitcher: ViewSwitcher
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
Registry.init(this)
|
||||
viewSwitcher = ViewSwitcher(this)
|
||||
|
||||
val inflater = LayoutInflater.from(this)
|
||||
inflater.inflate(R.layout.activity_main, viewSwitcher)
|
||||
inflater.inflate(R.layout.activity_nfc, viewSwitcher)
|
||||
|
||||
setContentView(viewSwitcher)
|
||||
Registry.init(this, this)
|
||||
Registry.scriptExecutor.defaultScript = cardCheckupScript()
|
||||
}
|
||||
|
||||
@ -38,6 +48,22 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScriptStarted() {
|
||||
this.runOnUiThread {
|
||||
viewSwitcher.showNext()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScriptFinished(result: CardCommand.Result) {
|
||||
this.runOnUiThread {
|
||||
viewSwitcher.showNext()
|
||||
}
|
||||
}
|
||||
|
||||
fun cancelNFC(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||
Registry.scriptExecutor.cancelScript()
|
||||
}
|
||||
|
||||
fun changePIN(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||
startCommand(ChangePINActivity::class)
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import im.status.keycard.connect.R
|
||||
import im.status.keycard.connect.Registry
|
||||
import im.status.keycard.connect.data.PINCache
|
||||
import im.status.keycard.connect.data.PIN_ACTIVITY_ATTEMPTS
|
||||
import im.status.keycard.connect.data.PIN_ACTIVITY_CARD_UID
|
||||
|
||||
|
@ -8,8 +8,6 @@ import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import im.status.keycard.connect.R
|
||||
import im.status.keycard.connect.Registry
|
||||
import im.status.keycard.connect.data.PIN_ACTIVITY_ATTEMPTS
|
||||
import im.status.keycard.connect.data.PIN_ACTIVITY_CARD_UID
|
||||
import im.status.keycard.connect.data.PUK_ACTIVITY_ATTEMPTS
|
||||
|
||||
class PUKActivity : AppCompatActivity() {
|
||||
|
33
app/src/main/res/layout/activity_nfc.xml
Normal file
33
app/src/main/res/layout/activity_nfc.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="?attr/actionBarSize"
|
||||
tools:context=".ui.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nfcPrompt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/nfc_prompt"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.2" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancelButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="128dp"
|
||||
android:onClick="cancelNFC"
|
||||
android:text="@android:string/cancel"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.498"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -11,4 +11,5 @@
|
||||
<string name="change_pin_prompt">New PIN</string>
|
||||
<string name="change_pin">Change PIN</string>
|
||||
<string name="puk_prompt" >Insert your PUK</string>
|
||||
<string name="nfc_prompt">Tap your card</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user