diff --git a/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/AcsNfcHandler.kt b/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/AcsNfcHandler.kt index 99ee017..6725dab 100644 --- a/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/AcsNfcHandler.kt +++ b/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/AcsNfcHandler.kt @@ -37,7 +37,7 @@ class AcsNfcHandler( private val mode: NfcHandlerMode = NfcHandlerMode.DEFAULT ) : NfcHandler, (Reader, Int) -> Unit { private var mediaTypes: List? = null - private var running = false + private var state = NfcHandler.NfcState.INITIALIZED private var readerService: AcsReaderService? = null private var chipReadListener: NfcHandler.OnChipReadListener? = null private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) @@ -68,7 +68,8 @@ class AcsNfcHandler( this.mediaTypes = mediaTypes Log.i(TAG, "start (${mediaTypes.joinToString(", ")}) @$ctx") - running = true + // FIXME: shouldn't running be set by AcsReaderService, after connection to the reader succeeded? + state = NfcHandler.NfcState.RUNNING Intent(ctx, AcsReaderService::class.java).also { intent -> ctx.bindService(intent, readerConnection, Context.BIND_AUTO_CREATE) @@ -84,14 +85,19 @@ class AcsNfcHandler( } override fun stop() { - running = false + state = NfcHandler.NfcState.STOPPED readerService?.cardHandler = null scope.cancel() Log.i(TAG, "stop @$ctx") } + @Deprecated("Use State instead") override fun isRunning(): Boolean { - return running + return state == NfcHandler.NfcState.RUNNING + } + + override fun getState(): NfcHandler.NfcState { + return state } private fun readUid(reader: Reader, slotNum: Int): String { diff --git a/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/AndroidNativeNfcHandler.kt b/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/AndroidNativeNfcHandler.kt index 8ea5a41..9d40a6a 100644 --- a/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/AndroidNativeNfcHandler.kt +++ b/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/AndroidNativeNfcHandler.kt @@ -2,7 +2,10 @@ package eu.pretix.libpretixnfc.android.hardware import Mf0aesKeySet import android.app.Activity +import android.content.BroadcastReceiver import android.content.Context +import android.content.Intent +import android.content.IntentFilter import android.nfc.NfcAdapter import android.nfc.NfcAdapter.FLAG_READER_NFC_A import android.nfc.NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK @@ -49,7 +52,7 @@ class AndroidNativeNfcHandler( private var mediaTypes: List? = null private val buzzer = ctx.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator? - private var running = false + private var state = NfcHandler.NfcState.INITIALIZED private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) val supportedTypes = listOf(ReusableMediaType.NFC_UID, ReusableMediaType.NFC_MF0AES) @@ -58,6 +61,24 @@ class AndroidNativeNfcHandler( val TAG = "AndroidNativeNfcHandler" } + private val nfcStateReceiver: BroadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent) { + if (intent.action != NfcAdapter.ACTION_ADAPTER_STATE_CHANGED) { + return + } + when (intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF)) { + NfcAdapter.STATE_OFF -> { + state = NfcHandler.NfcState.DISABLED + } + NfcAdapter.STATE_TURNING_OFF -> {} + NfcAdapter.STATE_ON -> { + _start() + } + NfcAdapter.STATE_TURNING_ON -> {} + } + } + } + override fun start(mediaTypes: List) { if (!supportedTypes.any { mediaTypes.contains(it) }) { return @@ -66,12 +87,22 @@ class AndroidNativeNfcHandler( this.mediaTypes = mediaTypes Log.i(TAG, "start (${mediaTypes.joinToString(", ")}) @$ctx") if (nfcAdapter == null) { + state = NfcHandler.NfcState.UNSUPPORTED throw NfcUnsupported() } + + val filter = IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED) + ctx.registerReceiver(nfcStateReceiver, filter) + if (!nfcAdapter!!.isEnabled) { + state = NfcHandler.NfcState.DISABLED throw NfcDisabled() } + _start() + } + + fun _start() { nfcAdapter!!.enableReaderMode( ctx, this, @@ -80,7 +111,7 @@ class AndroidNativeNfcHandler( putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 1200) } ) - running = true + state = NfcHandler.NfcState.RUNNING } override fun getMediaTypes(): List? { @@ -91,13 +122,19 @@ class AndroidNativeNfcHandler( if (!ctx.isDestroyed) { nfcAdapter?.disableReaderMode(ctx) } - running = false + state = NfcHandler.NfcState.STOPPED + ctx.unregisterReceiver(nfcStateReceiver) scope.cancel() Log.i(TAG, "stop @$ctx") } + @Deprecated("Use State instead") override fun isRunning(): Boolean { - return running + return state == NfcHandler.NfcState.RUNNING + } + + override fun getState(): NfcHandler.NfcState { + return state } override fun setOnChipReadListener(listener: NfcHandler.OnChipReadListener?) { diff --git a/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/NfcHandler.kt b/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/NfcHandler.kt index a7b1e7c..868de54 100644 --- a/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/NfcHandler.kt +++ b/libpretixnfc-android/src/main/java/eu/pretix/libpretixnfc/android/hardware/NfcHandler.kt @@ -19,6 +19,11 @@ interface NfcHandler { fun chipReadError(error: ChipReadError, identifier: String?) } + enum class NfcState { + INITIALIZED, RUNNING, STOPPED, + UNSUPPORTED, DISABLED + } + /** * Start listening for chips. Should e.g. be called in Activity.onResume(). */ @@ -30,8 +35,11 @@ interface NfcHandler { */ fun stop() + @Deprecated("Use State instead") fun isRunning(): Boolean + fun getState(): NfcState + fun getMediaTypes(): List? /**