@@ -6,6 +6,7 @@ import android.nfc.NdefMessage
6
6
import android.nfc.NdefRecord
7
7
import android.nfc.NfcAdapter
8
8
import android.nfc.NfcAdapter.*
9
+ import android.nfc.Tag
9
10
import android.nfc.tech.*
10
11
import android.os.Handler
11
12
import android.os.HandlerThread
@@ -24,6 +25,9 @@ import io.flutter.plugin.common.MethodCall
24
25
import io.flutter.plugin.common.MethodChannel
25
26
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
26
27
import io.flutter.plugin.common.MethodChannel.Result
28
+ import io.flutter.plugin.common.EventChannel
29
+ import io.flutter.plugin.common.EventChannel.EventSink
30
+ import io.flutter.plugin.common.EventChannel.StreamHandler
27
31
import org.json.JSONArray
28
32
import org.json.JSONObject
29
33
import java.io.IOException
@@ -45,6 +49,16 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
45
49
46
50
private lateinit var nfcHandlerThread: HandlerThread
47
51
private lateinit var nfcHandler: Handler
52
+ private lateinit var methodChannel: MethodChannel
53
+ private lateinit var eventChannel: EventChannel
54
+ private var eventSink: EventSink ? = null
55
+
56
+ public fun handleTag (tag : Tag ) {
57
+ val result = parseTag(tag)
58
+ Handler (Looper .getMainLooper()).post {
59
+ eventSink?.success(result)
60
+ }
61
+ }
48
62
49
63
private fun TagTechnology.transceive (data : ByteArray , timeout : Int? ): ByteArray {
50
64
if (timeout != null ) {
@@ -79,18 +93,178 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
79
93
result.error(" 500" , " Failed to post job to NFC Handler thread." , null )
80
94
}
81
95
}
96
+
97
+ private fun parseTag (tag : Tag ): String {
98
+ // common fields
99
+ val type: String
100
+ val id = tag.id.toHexString()
101
+ val standard: String
102
+ // ISO 14443 Type A
103
+ var atqa = " "
104
+ var sak = " "
105
+ // ISO 14443 Type B
106
+ var protocolInfo = " "
107
+ var applicationData = " "
108
+ // ISO 7816
109
+ var historicalBytes = " "
110
+ var hiLayerResponse = " "
111
+ // NFC-F / Felica
112
+ var manufacturer = " "
113
+ var systemCode = " "
114
+ // NFC-V
115
+ var dsfId = " "
116
+ // NDEF
117
+ var ndefAvailable = false
118
+ var ndefWritable = false
119
+ var ndefCanMakeReadOnly = false
120
+ var ndefCapacity = 0
121
+ var ndefType = " "
122
+
123
+ if (tag.techList.contains(NfcA ::class .java.name)) {
124
+ val aTag = NfcA .get(tag)
125
+ atqa = aTag.atqa.toHexString()
126
+ sak = byteArrayOf(aTag.sak.toByte()).toHexString()
127
+ tagTechnology = aTag
128
+ when {
129
+ tag.techList.contains(IsoDep ::class .java.name) -> {
130
+ standard = " ISO 14443-4 (Type A)"
131
+ type = " iso7816"
132
+ val isoDep = IsoDep .get(tag)
133
+ tagTechnology = isoDep
134
+ historicalBytes = isoDep.historicalBytes.toHexString()
135
+ }
136
+ tag.techList.contains(MifareClassic ::class .java.name) -> {
137
+ standard = " ISO 14443-3 (Type A)"
138
+ type = " mifare_classic"
139
+ with (MifareClassic .get(tag)) {
140
+ tagTechnology = this
141
+ mifareInfo = MifareInfo (
142
+ this .type,
143
+ size,
144
+ MifareClassic .BLOCK_SIZE ,
145
+ blockCount,
146
+ sectorCount
147
+ )
148
+ }
149
+ }
150
+ tag.techList.contains(MifareUltralight ::class .java.name) -> {
151
+ standard = " ISO 14443-3 (Type A)"
152
+ type = " mifare_ultralight"
153
+ with (MifareUltralight .get(tag)) {
154
+ tagTechnology = this
155
+ mifareInfo = MifareInfo .fromUltralight(this .type)
156
+ }
157
+ }
158
+ else -> {
159
+ standard = " ISO 14443-3 (Type A)"
160
+ type = " unknown"
161
+ }
162
+ }
163
+ } else if (tag.techList.contains(NfcB ::class .java.name)) {
164
+ val bTag = NfcB .get(tag)
165
+ protocolInfo = bTag.protocolInfo.toHexString()
166
+ applicationData = bTag.applicationData.toHexString()
167
+ if (tag.techList.contains(IsoDep ::class .java.name)) {
168
+ type = " iso7816"
169
+ standard = " ISO 14443-4 (Type B)"
170
+ val isoDep = IsoDep .get(tag)
171
+ tagTechnology = isoDep
172
+ hiLayerResponse = isoDep.hiLayerResponse.toHexString()
173
+ } else {
174
+ type = " unknown"
175
+ standard = " ISO 14443-3 (Type B)"
176
+ tagTechnology = bTag
177
+ }
178
+ } else if (tag.techList.contains(NfcF ::class .java.name)) {
179
+ standard = " ISO 18092 (FeliCa)"
180
+ type = " iso18092"
181
+ val fTag = NfcF .get(tag)
182
+ manufacturer = fTag.manufacturer.toHexString()
183
+ systemCode = fTag.systemCode.toHexString()
184
+ tagTechnology = fTag
185
+ } else if (tag.techList.contains(NfcV ::class .java.name)) {
186
+ standard = " ISO 15693"
187
+ type = " iso15693"
188
+ val vTag = NfcV .get(tag)
189
+ dsfId = vTag.dsfId.toHexString()
190
+ tagTechnology = vTag
191
+ } else {
192
+ type = " unknown"
193
+ standard = " unknown"
194
+ }
195
+
196
+ // detect ndef
197
+ if (tag.techList.contains(Ndef ::class .java.name)) {
198
+ val ndefTag = Ndef .get(tag)
199
+ ndefTechnology = ndefTag
200
+ ndefAvailable = true
201
+ ndefType = ndefTag.type
202
+ ndefWritable = ndefTag.isWritable
203
+ ndefCanMakeReadOnly = ndefTag.canMakeReadOnly()
204
+ ndefCapacity = ndefTag.maxSize
205
+ }
206
+
207
+ val jsonResult = JSONObject (mapOf (
208
+ " type" to type,
209
+ " id" to id,
210
+ " standard" to standard,
211
+ " atqa" to atqa,
212
+ " sak" to sak,
213
+ " historicalBytes" to historicalBytes,
214
+ " protocolInfo" to protocolInfo,
215
+ " applicationData" to applicationData,
216
+ " hiLayerResponse" to hiLayerResponse,
217
+ " manufacturer" to manufacturer,
218
+ " systemCode" to systemCode,
219
+ " dsfId" to dsfId,
220
+ " ndefAvailable" to ndefAvailable,
221
+ " ndefType" to ndefType,
222
+ " ndefWritable" to ndefWritable,
223
+ " ndefCanMakeReadOnly" to ndefCanMakeReadOnly,
224
+ " ndefCapacity" to ndefCapacity,
225
+ ))
226
+
227
+ if (mifareInfo != null ) {
228
+ with (mifareInfo!! ) {
229
+ jsonResult.put(" mifareInfo" , JSONObject (mapOf (
230
+ " type" to typeStr,
231
+ " size" to size,
232
+ " blockSize" to blockSize,
233
+ " blockCount" to blockCount,
234
+ " sectorCount" to sectorCount
235
+ )))
236
+ }
237
+ }
238
+
239
+ return jsonResult.toString()
240
+ }
82
241
}
83
242
84
243
override fun onAttachedToEngine (flutterPluginBinding : FlutterPlugin .FlutterPluginBinding ) {
85
244
nfcHandlerThread = HandlerThread (" NfcHandlerThread" )
86
245
nfcHandlerThread.start()
87
246
nfcHandler = Handler (nfcHandlerThread.looper)
88
247
89
- val channel = MethodChannel (flutterPluginBinding.binaryMessenger, " flutter_nfc_kit" )
90
- channel.setMethodCallHandler(this )
248
+ methodChannel = MethodChannel (flutterPluginBinding.binaryMessenger, " flutter_nfc_kit/method" )
249
+ methodChannel.setMethodCallHandler(this )
250
+
251
+ eventChannel = EventChannel (flutterPluginBinding.binaryMessenger, " flutter_nfc_kit/event" )
252
+ eventChannel.setStreamHandler(object : EventChannel .StreamHandler {
253
+ override fun onListen (arguments : Any? , events : EventChannel .EventSink ? ) {
254
+ if (events != null ) {
255
+ eventSink = events
256
+ }
257
+ }
258
+
259
+ override fun onCancel (arguments : Any? ) {
260
+ // No need to do anything here
261
+ }
262
+ })
91
263
}
92
264
93
265
override fun onDetachedFromEngine (binding : FlutterPlugin .FlutterPluginBinding ) {
266
+ methodChannel.setMethodCallHandler(null )
267
+ eventChannel.setStreamHandler(null )
94
268
nfcHandlerThread.quitSafely()
95
269
}
96
270
@@ -418,148 +592,8 @@ class FlutterNfcKitPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
418
592
val pollHandler = NfcAdapter .ReaderCallback { tag ->
419
593
pollingTimeoutTask?.cancel()
420
594
421
- // common fields
422
- val type: String
423
- val id = tag.id.toHexString()
424
- val standard: String
425
- // ISO 14443 Type A
426
- var atqa = " "
427
- var sak = " "
428
- // ISO 14443 Type B
429
- var protocolInfo = " "
430
- var applicationData = " "
431
- // ISO 7816
432
- var historicalBytes = " "
433
- var hiLayerResponse = " "
434
- // NFC-F / Felica
435
- var manufacturer = " "
436
- var systemCode = " "
437
- // NFC-V
438
- var dsfId = " "
439
- // NDEF
440
- var ndefAvailable = false
441
- var ndefWritable = false
442
- var ndefCanMakeReadOnly = false
443
- var ndefCapacity = 0
444
- var ndefType = " "
445
-
446
- if (tag.techList.contains(NfcA ::class .java.name)) {
447
- val aTag = NfcA .get(tag)
448
- atqa = aTag.atqa.toHexString()
449
- sak = byteArrayOf(aTag.sak.toByte()).toHexString()
450
- tagTechnology = aTag
451
- when {
452
- tag.techList.contains(IsoDep ::class .java.name) -> {
453
- standard = " ISO 14443-4 (Type A)"
454
- type = " iso7816"
455
- val isoDep = IsoDep .get(tag)
456
- tagTechnology = isoDep
457
- historicalBytes = isoDep.historicalBytes.toHexString()
458
- }
459
- tag.techList.contains(MifareClassic ::class .java.name) -> {
460
- standard = " ISO 14443-3 (Type A)"
461
- type = " mifare_classic"
462
- with (MifareClassic .get(tag)) {
463
- tagTechnology = this
464
- mifareInfo = MifareInfo (
465
- this .type,
466
- size,
467
- MifareClassic .BLOCK_SIZE ,
468
- blockCount,
469
- sectorCount
470
- )
471
- }
472
- }
473
- tag.techList.contains(MifareUltralight ::class .java.name) -> {
474
- standard = " ISO 14443-3 (Type A)"
475
- type = " mifare_ultralight"
476
- with (MifareUltralight .get(tag)) {
477
- tagTechnology = this
478
- mifareInfo = MifareInfo .fromUltralight(this .type)
479
- }
480
- }
481
- else -> {
482
- standard = " ISO 14443-3 (Type A)"
483
- type = " unknown"
484
- }
485
- }
486
- } else if (tag.techList.contains(NfcB ::class .java.name)) {
487
- val bTag = NfcB .get(tag)
488
- protocolInfo = bTag.protocolInfo.toHexString()
489
- applicationData = bTag.applicationData.toHexString()
490
- if (tag.techList.contains(IsoDep ::class .java.name)) {
491
- type = " iso7816"
492
- standard = " ISO 14443-4 (Type B)"
493
- val isoDep = IsoDep .get(tag)
494
- tagTechnology = isoDep
495
- hiLayerResponse = isoDep.hiLayerResponse.toHexString()
496
- } else {
497
- type = " unknown"
498
- standard = " ISO 14443-3 (Type B)"
499
- tagTechnology = bTag
500
- }
501
- } else if (tag.techList.contains(NfcF ::class .java.name)) {
502
- standard = " ISO 18092 (FeliCa)"
503
- type = " iso18092"
504
- val fTag = NfcF .get(tag)
505
- manufacturer = fTag.manufacturer.toHexString()
506
- systemCode = fTag.systemCode.toHexString()
507
- tagTechnology = fTag
508
- } else if (tag.techList.contains(NfcV ::class .java.name)) {
509
- standard = " ISO 15693"
510
- type = " iso15693"
511
- val vTag = NfcV .get(tag)
512
- dsfId = vTag.dsfId.toHexString()
513
- tagTechnology = vTag
514
- } else {
515
- type = " unknown"
516
- standard = " unknown"
517
- }
518
-
519
- // detect ndef
520
- if (tag.techList.contains(Ndef ::class .java.name)) {
521
- val ndefTag = Ndef .get(tag)
522
- ndefTechnology = ndefTag
523
- ndefAvailable = true
524
- ndefType = ndefTag.type
525
- ndefWritable = ndefTag.isWritable
526
- ndefCanMakeReadOnly = ndefTag.canMakeReadOnly()
527
- ndefCapacity = ndefTag.maxSize
528
- }
529
-
530
- val jsonResult = JSONObject (mapOf (
531
- " type" to type,
532
- " id" to id,
533
- " standard" to standard,
534
- " atqa" to atqa,
535
- " sak" to sak,
536
- " historicalBytes" to historicalBytes,
537
- " protocolInfo" to protocolInfo,
538
- " applicationData" to applicationData,
539
- " hiLayerResponse" to hiLayerResponse,
540
- " manufacturer" to manufacturer,
541
- " systemCode" to systemCode,
542
- " dsfId" to dsfId,
543
- " ndefAvailable" to ndefAvailable,
544
- " ndefType" to ndefType,
545
- " ndefWritable" to ndefWritable,
546
- " ndefCanMakeReadOnly" to ndefCanMakeReadOnly,
547
- " ndefCapacity" to ndefCapacity,
548
- ))
549
-
550
- if (mifareInfo != null ) {
551
- with (mifareInfo!! ) {
552
- jsonResult.put(" mifareInfo" , JSONObject (mapOf (
553
- " type" to typeStr,
554
- " size" to size,
555
- " blockSize" to blockSize,
556
- " blockCount" to blockCount,
557
- " sectorCount" to sectorCount
558
- )))
559
- }
560
- }
561
-
562
- result.success(jsonResult.toString())
595
+ val jsonResult = parseTag(tag)
596
+ result.success(jsonResult)
563
597
}
564
598
565
599
nfcAdapter.enableReaderMode(activity.get(), pollHandler, technologies, null )
0 commit comments