0

I need to read NFC tag when only user push a button.

The following is code that I wrote but it does not work.

I've tried that display NFC tag information to textview.
Nothing to display anything despite I hold up a NFC card. It looks like onNewIntent Event does not fire when NFC is present.

Why following code is not work?


Update:

Now I tried to pass techlist argument to enableForegroundDispatch. It does not work yet.

techlist = arrayOf(
            arrayOf(android.nfc.tech.NfcA::class.java.name),
            arrayOf(android.nfc.tech.NfcB::class.java.name),
            arrayOf(android.nfc.tech.IsoDep::class.java.name),
            arrayOf(android.nfc.tech.MifareClassic::class.java.name),
            arrayOf(android.nfc.tech.NfcV::class.java.name),
            arrayOf(android.nfc.tech.NfcF::class.java.name),
            arrayOf(android.nfc.tech.NdefFormatable::class.java.name),
            arrayOf(android.nfc.tech.MifareUltralight::class.java.name)
        )

class MainActivity : AppCompatActivity() {
    var pendintent: PendingIntent? = null
    var nfc_adapt: NfcAdapter? = null
    var iFilter: IntentFilter? = null
    var tview: TextView? = null
    var read_button:  Button? = null // read button
    var delete_button: Button? = null // delete button for content of text view that display tag information
    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tview = findViewById(R.id.textView) // 表示用のTextView
        nfc_adapt = NfcAdapter.getDefaultAdapter(applicationContext)
        pendintent = PendingIntent.getActivity(this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0
        )
        iFilter = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
        val iFilters = arrayOf<IntentFilter>(iFilter!!)

        read_button = findViewById(R.id.button)
        delete_button = findViewById(R.id.button2)
        delete_button!!.isEnabled = false

        read_button!!.setOnTouchListener(fun(v: View, m: MotionEvent) : Boolean {
            when (m.action) {
                MotionEvent.ACTION_DOWN -> {
                    tview!!.setBackgroundColor(Color.rgb(0,0,0))
                    tview!!.setTextColor(Color.rgb(0, 255, 0))
                    tview!!.text = "Now Reading A Tag"
                    Log.d(null, "ACTION UPPED")
                    nfc_adapt!!.enableForegroundDispatch(this, pendintent,iFilters, null)
                    return false
                }
                MotionEvent.ACTION_UP -> {
                    nfc_adapt!!.disableForegroundDispatch(this)
                    tview!!.text = ""
                    return false
                }
            }
            return false
        })

        // Delete contents of TextView

        delete_button!!.setOnClickListener {
            tview!!.text = ""
            tview!!.setBackgroundColor(Color.rgb(0, 0, 0))
            tview!!.setTextColor(Color.rgb(0, 255, 0))
            read_button!!.isEnabled = true
            it.isEnabled = false
        }

    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        val action: String? = intent.action
        if (action.equals(NfcAdapter.ACTION_TECH_DISCOVERED)) {
            var nfc_tag_array = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_TAG)
            if (nfc_tag_array == null) {
                tview?.setBackgroundColor(Color.YELLOW)
                tview?.setTextColor(Color.rgb(0,0,0))
                tview?.text =  "read a tag but does not contain tag data"
                return
            }
            val t = nfc_tag_array[0] as Tag?
            if (t == null) {
                tview!!.text = "Read a tag but it a null"
            } else {
                tview!!.text = t.toString() // print tag information as a string
            }
            tview!!.setBackgroundColor(Color.YELLOW)
            tview!!.setTextColor(Color.rgb(0,0,0))
            nfc_adapt!!.disableForegroundDispatch(this)
            read_button!!.isEnabled = false // disable read button until user push the delete button
            delete_button!!.isEnabled = true


        }
        else {
            // nothing to do
        }
    }
}
KiYugadgeter
  • 3,796
  • 7
  • 34
  • 74
  • Attach a debugger or puts some logging in, does `onNewIntent` fire when the tag is presented? And what type of data is on the tag? – Andrew Jul 22 '20 at 16:27
  • onNewIntent does not fire despite tag is presented. – KiYugadgeter Jul 23 '20 at 01:03
  • 1
    Thinking ahead a bit, I think you might get unreliable user input that will enable tag detection even when the button is released. The problem is with `enableForegroundDispatch` your application is paused and not the foreground App when a Tag is detected, Thus it is possible that your App won't be sent the Motion Up event and `disableForegroundDispatch` will never be called. Not your current problem but if you want to keep this behaviour you might find you have to move to using the `enableReaderMode` NFC API where the Tag detection is in a callback thread. – Andrew Jul 23 '20 at 10:08
  • Now I could read NFC tag with enaleReaderMode. How do I read extra data in tag (if exists) with Tag object that passed to callback? – KiYugadgeter Jul 24 '20 at 04:19
  • 1
    https://stackoverflow.com/a/59397667/2373819 (sorry in Java) gives an example of `enableReaderMode` API, the `onTagDiscovered` method is called with the `Tag` object which is what is passed in the `NfcAdapter.EXTRA_TAG` field of the intent. Just remember with `enableReaderMode` `onTagDiscovered` is in a separate thread, your app is not paused while reading is done, if you want to update a `Textview` from there you will need to use something like `runOnUiThread` – Andrew Jul 24 '20 at 08:41

0 Answers0