Skip to content

Commit 0e53a9d

Browse files
authored
Merge pull request #167 from knthm/implement-dedicated-handler-thread
feat: implement dedicated handler thread for IO operations
2 parents 22f94c3 + 829d0ea commit 0e53a9d

File tree

1 file changed

+33
-19
lines changed

1 file changed

+33
-19
lines changed

android/src/main/kotlin/im/nfc/flutter_nfc_kit/FlutterNfcKitPlugin.kt

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import android.nfc.NfcAdapter
88
import android.nfc.NfcAdapter.*
99
import android.nfc.tech.*
1010
import android.os.Handler
11+
import android.os.HandlerThread
1112
import android.os.Looper
1213
import im.nfc.flutter_nfc_kit.ByteUtils.canonicalizeData
1314
import im.nfc.flutter_nfc_kit.ByteUtils.hexToBytes
@@ -30,7 +31,6 @@ import java.lang.ref.WeakReference
3031
import java.lang.reflect.InvocationTargetException
3132
import java.util.*
3233
import kotlin.concurrent.schedule
33-
import kotlin.concurrent.thread
3434

3535

3636
class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
@@ -43,6 +43,9 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
4343
private var ndefTechnology: Ndef? = null
4444
private var mifareInfo: MifareInfo? = null
4545

46+
private lateinit var nfcHandlerThread: HandlerThread
47+
private lateinit var nfcHandler: Handler
48+
4649
private fun TagTechnology.transceive(data: ByteArray, timeout: Int?): ByteArray {
4750
if (timeout != null) {
4851
try {
@@ -53,13 +56,27 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
5356
val transceiveMethod = this.javaClass.getMethod("transceive", ByteArray::class.java)
5457
return transceiveMethod.invoke(this, data) as ByteArray
5558
}
59+
60+
private fun runOnNfcThread(result: Result, fn: () -> Unit) {
61+
if (!nfcHandler.post(fn)) {
62+
result.error("500", "Failed to post job to NFC Handler thread.", null)
63+
}
64+
}
5665
}
5766

5867
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
68+
nfcHandlerThread = HandlerThread("NfcHandlerThread")
69+
nfcHandlerThread.start()
70+
nfcHandler = Handler(nfcHandlerThread.looper)
71+
5972
val channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_nfc_kit")
6073
channel.setMethodCallHandler(this)
6174
}
6275

76+
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
77+
nfcHandlerThread.quitSafely()
78+
}
79+
6380
override fun onMethodCall(call: MethodCall, result: Result) {
6481
handleMethodCall(call, MethodResultWrapper(result))
6582
}
@@ -113,14 +130,14 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
113130
val timeout = call.argument<Int>("timeout")!!
114131
// technology and option bits are set in Dart code
115132
val technologies = call.argument<Int>("technologies")!!
116-
thread {
133+
runOnNfcThread(result) {
117134
pollTag(nfcAdapter, result, timeout, technologies)
118135
}
119136
}
120137

121138
"finish" -> {
122139
pollingTimeoutTask?.cancel()
123-
thread {
140+
runOnNfcThread(result) {
124141
try {
125142
val tagTech = tagTechnology
126143
if (tagTech != null && tagTech.isConnected) {
@@ -155,7 +172,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
155172
}
156173
val (sendingBytes, sendingHex) = canonicalizeData(data)
157174

158-
thread {
175+
runOnNfcThread(result) {
159176
try {
160177
switchTechnology(tagTech, ndefTechnology)
161178
val timeout = call.argument<Int>("timeout")
@@ -187,7 +204,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
187204
"readNDEF" -> {
188205
if (!ensureNDEF()) return
189206
val ndef = ndefTechnology!!
190-
thread {
207+
runOnNfcThread(result) {
191208
try {
192209
switchTechnology(ndef, tagTechnology)
193210
// read NDEF message
@@ -236,7 +253,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
236253
result.error("405", "Tag not writable", null)
237254
return
238255
}
239-
thread {
256+
runOnNfcThread(result) {
240257
try {
241258
switchTechnology(ndef, tagTechnology)
242259
// generate NDEF message
@@ -283,7 +300,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
283300
result.error("405", "Tag not writable", null)
284301
return
285302
}
286-
thread {
303+
runOnNfcThread(result) {
287304
try {
288305
switchTechnology(ndef, tagTechnology)
289306
if (ndef.makeReadOnly()) {
@@ -316,22 +333,22 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
316333
}
317334
val keyA = call.argument<Any>("keyA")
318335
val keyB = call.argument<Any>("keyB")
319-
thread {
336+
runOnNfcThread(result) {
320337
try {
321338
val tag = tagTech as MifareClassic
322339
switchTechnology(tagTech, ndefTechnology)
323340
// key A takes precedence if present
324-
val success = if (keyA != null) {
341+
if (keyA != null) {
325342
val (key, _) = canonicalizeData(keyA)
326-
tag.authenticateSectorWithKeyA(index, key)
343+
val authStatus = tag.authenticateSectorWithKeyA(index, key)
344+
result.success(authStatus)
327345
} else if (keyB != null) {
328346
val (key, _) = canonicalizeData(keyB)
329-
tag.authenticateSectorWithKeyB(index, key)
347+
val authStatus = tag.authenticateSectorWithKeyB(index, key)
348+
result.success(authStatus)
330349
} else {
331350
result.error("400", "No keys provided", null)
332-
return@thread
333351
}
334-
result.success(success)
335352
} catch (ex: IOException) {
336353
Log.e(TAG, "Authenticate block error", ex)
337354
result.error("500", "Authentication error", ex.localizedMessage)
@@ -351,7 +368,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
351368
result.error("400", "Invalid block/page index $index, should be in (0, $maxBlock)", null)
352369
return
353370
}
354-
thread {
371+
runOnNfcThread(result) {
355372
try {
356373
switchTechnology(tagTech, ndefTechnology)
357374
tagTech.readBlock(index, result)
@@ -374,7 +391,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
374391
result.error("400", "Invalid sector index $index, should be in (0, $maxSector)", null)
375392
return
376393
}
377-
thread {
394+
runOnNfcThread(result) {
378395
try {
379396
val tag = tagTech as MifareClassic
380397
switchTechnology(tagTech, ndefTechnology)
@@ -407,7 +424,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
407424
result.error("400", "Invalid data size ${bytes.size}, should be ${mifareInfo!!.blockSize}", null)
408425
return
409426
}
410-
thread {
427+
runOnNfcThread(result) {
411428
try {
412429
switchTechnology(tagTech, ndefTechnology)
413430
tagTech.writeBlock(index, bytes, result)
@@ -421,9 +438,6 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
421438
}
422439
}
423440

424-
425-
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {}
426-
427441
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
428442
activity = WeakReference(binding.activity)
429443
}

0 commit comments

Comments
 (0)