How to read NFC Beam and tags?

404 Views Asked by At

I've been struggling with this for a couple of days now and I need help. I want to read HCE and beams with my app, independently they work fine, but when I want to put them together the onTagDiscovered is the one always getting called and never gets any info when it comes from beams.

I think is possible, but I'm new to this so probably I'm doing something crazy.

Here is the code:

class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {

    private var command: ByteArray? = null
    private lateinit var mNFCAdapter: NfcAdapter

    companion object {
        val TAG: String = com.solano.nfc.isodep.reader.MainActivity::class.java.name
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "onCreate")
        setContentView(R.layout.activity_main)
        mNFCAdapter = NfcAdapter.getDefaultAdapter(this)

        command = Utils.hexStringToByteArray("00A4040007A220100247100100")
    }

    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume")

        intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
        val pendingIntent =
            PendingIntent.getActivity(this, 0, intent, 0)

        val filters = arrayOfNulls<IntentFilter>(1)
        val techList =
            arrayOf<Array<String>>()

        // Filter for nfc tag discovery

        // Filter for nfc tag discovery
        filters[0] = IntentFilter()
        filters[0]!!.addAction(NfcAdapter.ACTION_NDEF_DISCOVERED)
        filters[0]!!.addCategory(Intent.CATEGORY_DEFAULT)
        filters[0]!!.addDataType("application/vnd.com.example.myapp")

        if(::mNFCAdapter.isInitialized){
            val flags = NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK
            mNFCAdapter.enableReaderMode(this, this, flags, intent.extras)
            mNFCAdapter.enableForegroundDispatch(this, pendingIntent, filters, techList)
        }
    }

    override fun onPause() {
        super.onPause()
        Log.d(TAG, "onPause")
        mNFCAdapter.disableReaderMode(this)
        mNFCAdapter.disableForegroundDispatch(this)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        Log.d(TAG, "onNewIntent ${intent!!.action}")
        handleIntents(intent)
    }

    private fun handleIntents(intent: Intent?) {
        if (true) {
            val rawMessages = intent!!.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES
            )
            val message =
                rawMessages!![0] as NdefMessage // only one message transferred
            tvMain.text = String(message.records[0].payload)
        } else tvMain.text = "Waiting for NDEF Message"
    }

    override fun onTagDiscovered(tag: Tag?) {
        Log.d(TAG, "onTagDiscovered")
        try{
            val nDef = Ndef.get(tag)
            val isoDep = IsoDep.get(tag)

            if (nDef != null) {
                Log.d(TAG, "NDEF is supported")
            } else if (isoDep != null) {
                Log.d(TAG, "ISO-Dep is supported")
                if(!isoDep.isConnected){
                    isoDep.connect()
                    val response = isoDep.transceive(command)
                    val status = Utils.getStatus(response!!)
                    if(status == "9000") {
                        Log.d(TAG, "OK\n${String(response)}")
                    } else {
                        Log.d(TAG, "WTF Status code: $status")
                    }
                    isoDep.close()
                }
            }

        } catch (ex: Exception) {
            Log.d(TAG, ex.message)
        }
    }
}
1

There are 1 best solutions below

4
On

I'm not sure why you are using both enableReaderMode and enableForegroundDispatch as they are just different API's to do the same thing (read tags) BUT enableReaderMode Disables the deprecated Android Beam if available.

https://developer.android.com/reference/android/nfc/NfcAdapter#enableReaderMode(android.app.Activity,%20android.nfc.NfcAdapter.ReaderCallback,%20int,%20android.os.Bundle)

In this mode the NFC controller will only act as an NFC tag reader/writer, thus disabling any peer-to-peer (Android Beam) and card-emulation modes of the NFC adapter on this device.

I would just use enableForegroundDispatch