@@ -8,6 +8,7 @@ import android.nfc.NfcAdapter
8
8
import android.nfc.NfcAdapter.*
9
9
import android.nfc.tech.*
10
10
import android.os.Handler
11
+ import android.os.HandlerThread
11
12
import android.os.Looper
12
13
import im.nfc.flutter_nfc_kit.ByteUtils.canonicalizeData
13
14
import im.nfc.flutter_nfc_kit.ByteUtils.hexToBytes
@@ -30,7 +31,6 @@ import java.lang.ref.WeakReference
30
31
import java.lang.reflect.InvocationTargetException
31
32
import java.util.*
32
33
import kotlin.concurrent.schedule
33
- import kotlin.concurrent.thread
34
34
35
35
36
36
class FlutterNfcKitPlugin : FlutterPlugin , MethodCallHandler , ActivityAware {
@@ -43,6 +43,9 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
43
43
private var ndefTechnology: Ndef ? = null
44
44
private var mifareInfo: MifareInfo ? = null
45
45
46
+ private lateinit var nfcHandlerThread: HandlerThread
47
+ private lateinit var nfcHandler: Handler
48
+
46
49
private fun TagTechnology.transceive (data : ByteArray , timeout : Int? ): ByteArray {
47
50
if (timeout != null ) {
48
51
try {
@@ -53,13 +56,27 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
53
56
val transceiveMethod = this .javaClass.getMethod(" transceive" , ByteArray ::class .java)
54
57
return transceiveMethod.invoke(this , data) as ByteArray
55
58
}
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
+ }
56
65
}
57
66
58
67
override fun onAttachedToEngine (flutterPluginBinding : FlutterPlugin .FlutterPluginBinding ) {
68
+ nfcHandlerThread = HandlerThread (" NfcHandlerThread" )
69
+ nfcHandlerThread.start()
70
+ nfcHandler = Handler (nfcHandlerThread.looper)
71
+
59
72
val channel = MethodChannel (flutterPluginBinding.binaryMessenger, " flutter_nfc_kit" )
60
73
channel.setMethodCallHandler(this )
61
74
}
62
75
76
+ override fun onDetachedFromEngine (binding : FlutterPlugin .FlutterPluginBinding ) {
77
+ nfcHandlerThread.quitSafely()
78
+ }
79
+
63
80
override fun onMethodCall (call : MethodCall , result : Result ) {
64
81
handleMethodCall(call, MethodResultWrapper (result))
65
82
}
@@ -113,14 +130,14 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
113
130
val timeout = call.argument<Int >(" timeout" )!!
114
131
// technology and option bits are set in Dart code
115
132
val technologies = call.argument<Int >(" technologies" )!!
116
- thread {
133
+ runOnNfcThread(result) {
117
134
pollTag(nfcAdapter, result, timeout, technologies)
118
135
}
119
136
}
120
137
121
138
" finish" -> {
122
139
pollingTimeoutTask?.cancel()
123
- thread {
140
+ runOnNfcThread(result) {
124
141
try {
125
142
val tagTech = tagTechnology
126
143
if (tagTech != null && tagTech.isConnected) {
@@ -155,7 +172,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
155
172
}
156
173
val (sendingBytes, sendingHex) = canonicalizeData(data)
157
174
158
- thread {
175
+ runOnNfcThread(result) {
159
176
try {
160
177
switchTechnology(tagTech, ndefTechnology)
161
178
val timeout = call.argument<Int >(" timeout" )
@@ -187,7 +204,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
187
204
" readNDEF" -> {
188
205
if (! ensureNDEF()) return
189
206
val ndef = ndefTechnology!!
190
- thread {
207
+ runOnNfcThread(result) {
191
208
try {
192
209
switchTechnology(ndef, tagTechnology)
193
210
// read NDEF message
@@ -236,7 +253,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
236
253
result.error(" 405" , " Tag not writable" , null )
237
254
return
238
255
}
239
- thread {
256
+ runOnNfcThread(result) {
240
257
try {
241
258
switchTechnology(ndef, tagTechnology)
242
259
// generate NDEF message
@@ -283,7 +300,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
283
300
result.error(" 405" , " Tag not writable" , null )
284
301
return
285
302
}
286
- thread {
303
+ runOnNfcThread(result) {
287
304
try {
288
305
switchTechnology(ndef, tagTechnology)
289
306
if (ndef.makeReadOnly()) {
@@ -316,22 +333,22 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
316
333
}
317
334
val keyA = call.argument<Any >(" keyA" )
318
335
val keyB = call.argument<Any >(" keyB" )
319
- thread {
336
+ runOnNfcThread(result) {
320
337
try {
321
338
val tag = tagTech as MifareClassic
322
339
switchTechnology(tagTech, ndefTechnology)
323
340
// key A takes precedence if present
324
- val success = if (keyA != null ) {
341
+ if (keyA != null ) {
325
342
val (key, _) = canonicalizeData(keyA)
326
- tag.authenticateSectorWithKeyA(index, key)
343
+ val authStatus = tag.authenticateSectorWithKeyA(index, key)
344
+ result.success(authStatus)
327
345
} else if (keyB != null ) {
328
346
val (key, _) = canonicalizeData(keyB)
329
- tag.authenticateSectorWithKeyB(index, key)
347
+ val authStatus = tag.authenticateSectorWithKeyB(index, key)
348
+ result.success(authStatus)
330
349
} else {
331
350
result.error(" 400" , " No keys provided" , null )
332
- return @thread
333
351
}
334
- result.success(success)
335
352
} catch (ex: IOException ) {
336
353
Log .e(TAG , " Authenticate block error" , ex)
337
354
result.error(" 500" , " Authentication error" , ex.localizedMessage)
@@ -351,7 +368,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
351
368
result.error(" 400" , " Invalid block/page index $index , should be in (0, $maxBlock )" , null )
352
369
return
353
370
}
354
- thread {
371
+ runOnNfcThread(result) {
355
372
try {
356
373
switchTechnology(tagTech, ndefTechnology)
357
374
tagTech.readBlock(index, result)
@@ -374,7 +391,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
374
391
result.error(" 400" , " Invalid sector index $index , should be in (0, $maxSector )" , null )
375
392
return
376
393
}
377
- thread {
394
+ runOnNfcThread(result) {
378
395
try {
379
396
val tag = tagTech as MifareClassic
380
397
switchTechnology(tagTech, ndefTechnology)
@@ -407,7 +424,7 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
407
424
result.error(" 400" , " Invalid data size ${bytes.size} , should be ${mifareInfo!! .blockSize} " , null )
408
425
return
409
426
}
410
- thread {
427
+ runOnNfcThread(result) {
411
428
try {
412
429
switchTechnology(tagTech, ndefTechnology)
413
430
tagTech.writeBlock(index, bytes, result)
@@ -421,9 +438,6 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
421
438
}
422
439
}
423
440
424
-
425
- override fun onDetachedFromEngine (binding : FlutterPlugin .FlutterPluginBinding ) {}
426
-
427
441
override fun onAttachedToActivity (binding : ActivityPluginBinding ) {
428
442
activity = WeakReference (binding.activity)
429
443
}
0 commit comments