11package io.flutter.plugins.nfcmanager
22
33import android.app.Activity
4+ import android.content.Intent
45import android.nfc.NfcAdapter
56import android.nfc.Tag
67import android.nfc.tech.IsoDep
@@ -22,20 +23,72 @@ import io.flutter.plugin.common.MethodCall
2223import io.flutter.plugin.common.MethodChannel
2324import io.flutter.plugin.common.MethodChannel.MethodCallHandler
2425import io.flutter.plugin.common.MethodChannel.Result
26+ import io.flutter.plugin.common.EventChannel;
27+ import io.flutter.plugin.common.EventChannel.EventSink
28+ import io.flutter.plugin.common.EventChannel.StreamHandler
2529import java.io.IOException
2630import java.lang.Exception
2731import java.util.*
2832
29- class NfcManagerPlugin : FlutterPlugin , MethodCallHandler , ActivityAware {
33+ class NfcManagerPlugin : FlutterPlugin , MethodCallHandler , ActivityAware {
3034 private lateinit var channel : MethodChannel
3135 private lateinit var activity: Activity
3236 private lateinit var tags: MutableMap <String , Tag >
37+
38+ private var tagFromIntent: Tag ? = null
39+ private var sinkTagDiscoveredEvents = ArrayList <EventSink >()
40+
41+
3342 private var adapter: NfcAdapter ? = null
3443 private var connectedTech: TagTechnology ? = null
3544
3645 override fun onAttachedToEngine (binding : FlutterPlugin .FlutterPluginBinding ) {
37- channel = MethodChannel (binding.binaryMessenger, " plugins.flutter.io/nfc_manager" )
46+ val baseChannelName = " plugins.flutter.io/nfc_manager"
47+
48+ channel = MethodChannel (binding.binaryMessenger, baseChannelName)
3849 channel.setMethodCallHandler(this )
50+
51+ EventChannel (binding.binaryMessenger,
52+ baseChannelName + " /stream" ).setStreamHandler(
53+ object : StreamHandler {
54+ private lateinit var currentEvents : EventSink
55+
56+ override fun onListen (arguments : Any? , events : EventSink ) {
57+ if (sinkTagDiscoveredEvents.isEmpty()) {
58+ if (Build .VERSION .SDK_INT < Build .VERSION_CODES .KITKAT ) {
59+ events.error(" unavailable" , " Requires API level 19." , null )
60+ } else {
61+ val adapter = adapter ? : run {
62+ events.error(" unavailable" , " NFC is not available for device." , null )
63+ return
64+ }
65+
66+ var argMaps = arguments as HashMap <String ,Any ?>
67+ adapter.enableReaderMode(activity, NfcAdapter .ReaderCallback {
68+ activity.runOnUiThread { broadcastPreparedTag(it) }
69+ }, getFlags(argMaps[" pollingOptions" ] as List <String >), null )
70+ }
71+ }
72+
73+ currentEvents = events;
74+ sinkTagDiscoveredEvents.add(currentEvents);
75+
76+ tagFromIntent?.let {
77+ currentEvents.success(prepareTag(it))
78+ tagFromIntent = null
79+ }
80+ }
81+
82+ override fun onCancel (arguments : Any? ) {
83+ sinkTagDiscoveredEvents.remove(currentEvents);
84+
85+ if (sinkTagDiscoveredEvents.isEmpty()) {
86+ adapter?.disableReaderMode(activity)
87+ }
88+ }
89+ }
90+ )
91+
3992 adapter = NfcAdapter .getDefaultAdapter(binding.applicationContext)
4093 tags = mutableMapOf ()
4194 }
@@ -46,6 +99,24 @@ class NfcManagerPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
4699
47100 override fun onAttachedToActivity (binding : ActivityPluginBinding ) {
48101 activity = binding.activity
102+
103+ binding.addOnNewIntentListener(fun (intent : Intent ? ): Boolean {
104+ var tagProcessed = false ;
105+
106+ if (intent != null ){
107+ val tag = processIntent(intent)
108+
109+
110+ if (tag != null ) {
111+ broadcastPreparedTag(tag)
112+ tagProcessed = true
113+ }
114+ }
115+
116+ return tagProcessed
117+ })
118+
119+ processIntent(activity.intent)
49120 }
50121
51122 override fun onDetachedFromActivity () {
@@ -104,11 +175,11 @@ class NfcManagerPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
104175 result.error(" unavailable" , " NFC is not available for device." , null )
105176 return
106177 }
107- adapter.enableReaderMode(activity, {
108- val handle = UUID .randomUUID().toString()
109- tags[handle] = it
110- activity.runOnUiThread { channel.invokeMethod(" onDiscovered" , getTagMap(it).toMutableMap().apply { put(" handle" , handle) }) }
178+
179+ adapter.enableReaderMode(activity, NfcAdapter .ReaderCallback {
180+ activity.runOnUiThread { channel.invokeMethod(" onDiscovered" , prepareTag(it)) }
111181 }, getFlags(call.argument<List <String >>(" pollingOptions" )!! ), null )
182+
112183 result.success(null )
113184 }
114185 }
@@ -345,4 +416,24 @@ class NfcManagerPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
345416 connectedTech = tech
346417 }
347418 }
419+
420+ private fun processIntent (intent : Intent ) : Tag ? {
421+ tagFromIntent = intent?.getParcelableExtra(NfcAdapter .EXTRA_TAG )
422+
423+ return tagFromIntent
424+ }
425+
426+ private fun broadcastPreparedTag (tag : Tag ) {
427+ sinkTagDiscoveredEvents.forEach {
428+ val preparedTag = prepareTag(tag)
429+ it.success(preparedTag)
430+ }
431+ }
432+
433+ private fun prepareTag (tag : Tag ): MutableMap <String , Any ?> {
434+ val handle = UUID .randomUUID().toString()
435+ tags[handle] = tag
436+
437+ return getTagMap(tag).toMutableMap().apply { put(" handle" , handle) }
438+ }
348439}
0 commit comments