androidkotlinnfcsamsung

NFC reader works perfect when app is closed and on devices as Pixel, Xiaomi but not Samsung


I have a issue with Samsung devices. My NFC reader works perfect on Pixels, Xiaomi with and without app opened. However, on Samsung devices, it can only be worked when app is closed. When app is opened, I don't event see the NFC tag is detected on logcat. Here my NFCManager:

class NFCManager( val context: Context, private val onTagReadCallback: (String) -> Unit = {} ) {
private var isNFCToastShown: Boolean = false
private var mNfcAdapter: NfcAdapter? = null
private var lastLink: String? = null
lateinit var pendingIntent: PendingIntent
lateinit var intentFiltersArray: Array<IntentFilter>

fun init(activity: AppCompatActivity) {

    mNfcAdapter = NfcAdapter.getDefaultAdapter(activity)
    val intent = Intent(activity, javaClass).apply {
        addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
    }
    pendingIntent = PendingIntent.getActivity(
        activity, 0, intent,
        PendingIntent.FLAG_MUTABLE
    )
    val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {
        try {
            addDataType("*/*")    /* Handles all MIME based dispatches.
                             You should specify only the ones that you need. */
        } catch (e: IntentFilter.MalformedMimeTypeException) {
            throw RuntimeException("fail", e)
        }
    }
    val techDetected = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED).apply {
        try {
            addDataType("*/*")    /* Handles all MIME based dispatches.
                             You should specify only the ones that you need. */
        } catch (e: IntentFilter.MalformedMimeTypeException) {
            throw RuntimeException("fail", e)
        }
    }
    val tagDetected = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED).apply {
        try {
            addDataType("*/*")    /* Handles all MIME based dispatches.
                             You should specify only the ones that you need. */
        } catch (e: IntentFilter.MalformedMimeTypeException) {
            throw RuntimeException("fail", e)
        }
    }

    intentFiltersArray = arrayOf(ndef, techDetected, tagDetected)
}

private fun handleLink(link: String) {
    if (link != lastLink) {
        lastLink = link
        Handler(Looper.getMainLooper()).postDelayed({
            lastLink = null
        }, 4000)
        Timber.d("NFC NFCManager onShowTransaction : " + link)
        link.let(onTagReadCallback)
    }
}

fun enableNFC(activity: AppCompatActivity) {
    Timber.d("NFC enable nfc")
    if (mNfcAdapter == null) {
        init(activity)
    }
    if (mNfcAdapter != null) {
        if (!mNfcAdapter!!.isEnabled) {
            // Nfc is disabled
        }
        mNfcAdapter!!.enableReaderMode(activity, {
            val ndef = Ndef.get(it)
            if (ndef != null) {
                ndef.connect()
                val ndefMessage = ndef.ndefMessage
                if (ndefMessage != null) {
                    val records = ndefMessage.records
                    for (record in records) {
                        if (record.toUri() != null) {
                            val link = record.toUri().toString()
                            handleLink(link)
                        }
                    }
                }
                ndef.close()
            } else {
                Handler(Looper.getMainLooper()).postDelayed({
                    Toast.makeText(
                        activity,
                        activity.getString(R.string.nfc_manager_wrong_nfc_format),
                        Toast.LENGTH_SHORT
                    ).show()
                }, 100)
            }
        }, NfcAdapter.FLAG_READER_NFC_A, Bundle.EMPTY)
        mNfcAdapter!!.enableForegroundDispatch(
            activity,
            pendingIntent,
            intentFiltersArray,
            arrayOf(
                arrayOf(
                    Ndef::class.java.name,
                    NfcV::class.java.name,
                    NfcF::class.java.name,
                    NfcA::class.java.name,
                    NfcB::class.java.name
                )
            )
        )
    } else {
        /*
        if (!isNFCToastShown) {
            Toast.makeText(
                activity,
                activity.getString(R.string.nfc_manager_no_nfc_module),
                Toast.LENGTH_SHORT
            ).show()
            isNFCToastShown = true
        }

         */
    }
}

fun disableNFC(activity: AppCompatActivity) {
    Timber.d("NFC disable nfc")
    mNfcAdapter?.disableForegroundDispatch(activity)
    mNfcAdapter?.disableReaderMode(activity)
}

I enabled this manager onResume and disable it on onPause.

My manifest:

<uses-permission android:name="android.permission.NFC" /> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" />  
          <data android:mimeType="*/*" />
        </intent-filter>

        <intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT" />

            <data android:host="${deepLinkUri}" />

            <data android:pathPrefix="/c/" />

            <data android:scheme="https" />
        </intent-filter>

        <meta-data
            android:name="android.nfc.action.TECH_DISCOVERED"
            android:resource="@xml/techlist" />`

Really need some helps here cause I don't understand this weird behavior. I try an reader NFC app, no issue detected.

I want some helps to find out the issue with NFC reader on Samsung Devices


Solution

  • People have reported that on some devices NFC won't work at the same time as the camera especially on Samsung devices.

    It is believed that this is a choice by the Hardware manufacturer, may be the NFC radio waves interfere with the very large and sensitive Camera chips?