You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android NFC应用封装NfcManager后检测标签时onNewIntent方法未触发问题排查求助

问题排查与解决方案

我帮你定位到了核心问题:NfcManager中创建PendingIntent时指定了错误的目标组件,导致NFC触发的Intent无法正确发送到你的MainActivity,所以onNewIntent始终不会被调用。下面是具体分析和修正方案:

错误根源分析

在你封装的NfcManager.setupNFC()方法中,创建PendingIntent的代码是:

mPendingIntent = PendingIntent.getActivity(activity, 0, Intent(
        activity, javaClass)
        .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0)

这里的javaClass指的是NfcManager.Companion的类对象,而不是你的MainActivity类!NFC系统会尝试启动这个非Activity类,自然无法触发MainActivityonNewIntent方法。

对比你能正常工作的代码,在MainActivity.setNfcIntent()中,javaClass是当前MainActivity的类对象,所以Intent能正确路由到目标Activity。

其他附带问题

除了核心的PendingIntent错误,还有两个小问题需要修正:

  1. checkNFC()中用activity.applicationContext创建AlertDialog,Dialog需要依附于Activity上下文,用Application Context可能导致弹窗异常;
  2. onActivityResultOutSourced()中的逻辑完全搞反了:当前代码是“如果NFC已启用就finish Activity”,这明显不符合需求,应该是“如果NFC未启用才提示并finish”。

修正后的NfcManager代码

class NfcManager {
    companion object {
        private var mNfcAdapter: NfcAdapter? = null
        private var mPendingIntent: PendingIntent? = null
        private lateinit var writeTagFilters: Array<IntentFilter>
        private lateinit var mTechLists: Array<Array<String>>

        /**
         * Check the availability of NFC interface and let the user enable them
         * if not active during the activity creation
         */
        fun checkNFC(@NonNull activity: Activity) {
            if (activity.packageManager.hasSystemFeature(PackageManager.FEATURE_NFC)) {
                mNfcAdapter = NfcAdapter.getDefaultAdapter(activity)
                if (mNfcAdapter != null && !mNfcAdapter!!.isEnabled) {
                    // 修正:使用Activity上下文创建Dialog
                    AlertDialog.Builder(activity)
                            .setTitle(activity.resources.getString(R.string.dialog_nfc_not_enabled_title))
                            .setMessage(activity.resources.getString(R.string.dialog_nfc_not_enabled_msg))
                            .setPositiveButton(activity.resources.getString(R.string.dialog_nfc_not_enabled_positive_btn)
                            ) { _, _ ->
                                activity.startActivityForResult(Intent(Settings.ACTION_NFC_SETTINGS), MainActivity.ENABLE_NFC_REQUEST_CODE)
                            }
                            .setNegativeButton(activity.resources.getString(R.string.dialog_nfc_not_enabled_negative_btn)
                            ) { _, _ ->
                                Toast.makeText(activity, activity.resources.getString(R.string.nfc_not_enabled), Toast.LENGTH_LONG).show()
                                activity.finish()
                            }.show()
                }
            } else {
                Toast.makeText(activity, activity.resources.getString(R.string.nfc_not_enabled), Toast.LENGTH_LONG).show()
                activity.finish()
            }
        }

        /**
         * Create a generic PendingIntent that will be delivered to this activity.
         * The NFC stack will fill in the intent with the details of the discovered
         * tag before delivering it to this activity.
         */
        fun setupNFC(@NonNull activity: Activity) {
            // 核心修正:指定目标Activity为传入的activity的class,而非NfcManager的class
            mPendingIntent = PendingIntent.getActivity(
                activity,
                0,
                Intent(activity, activity.javaClass)
                    .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
                0
            )
            val tagDetected = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
            writeTagFilters = arrayOf(tagDetected)
            mTechLists = arrayOf(arrayOf(
                    NfcV::class.java.name
            ))
        }

        fun onActivityResultOutSourced(@NonNull activity: Activity) {
            mNfcAdapter = NfcAdapter.getDefaultAdapter(activity)
            // 修正逻辑:NFC未启用才提示并finish
            if (mNfcAdapter == null || !mNfcAdapter!!.isEnabled) {
                Toast.makeText(activity, activity.resources.getString(R.string.nfc_not_enabled), Toast.LENGTH_LONG).show()
                activity.finish()
            } else {
                Toast.makeText(activity, activity.resources.getString(R.string.nfc_enabled_success), Toast.LENGTH_SHORT).show()
            }
        }

        fun onResumeOutSourced(@NonNull activity: Activity) {
            if (mNfcAdapter != null) {
                mNfcAdapter!!.enableForegroundDispatch(activity, mPendingIntent, writeTagFilters, mTechLists)
            }
        }

        fun onPauseOutSourced(@NonNull activity: Activity) {
            if (mNfcAdapter != null) mNfcAdapter!!.disableForegroundDispatch(activity)
        }
    }
}

使用注意事项

  1. 确保你在strings.xml中添加了nfc_enabled_success对应的字符串,或者根据你的需求调整提示内容;
  2. MainActivityonNewIntent逻辑无需修改,保持现有代码即可;
  3. 确认MainActivity的启动模式没有冲突(你已经设置了FLAG_ACTIVITY_SINGLE_TOP,这是正确的,确保新Intent会触发onNewIntent而不是重新创建Activity)。

这样修改后,你的NfcManager封装就能正常工作,NFC标签扫描事件会正确触发MainActivityonNewIntent方法。

内容的提问来源于stack exchange,提问作者Martin Denion

火山引擎 最新活动