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类,自然无法触发MainActivity的onNewIntent方法。
对比你能正常工作的代码,在MainActivity.setNfcIntent()中,javaClass是当前MainActivity的类对象,所以Intent能正确路由到目标Activity。
其他附带问题
除了核心的PendingIntent错误,还有两个小问题需要修正:
checkNFC()中用activity.applicationContext创建AlertDialog,Dialog需要依附于Activity上下文,用Application Context可能导致弹窗异常;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) } } }
使用注意事项
- 确保你在
strings.xml中添加了nfc_enabled_success对应的字符串,或者根据你的需求调整提示内容; MainActivity的onNewIntent逻辑无需修改,保持现有代码即可;- 确认
MainActivity的启动模式没有冲突(你已经设置了FLAG_ACTIVITY_SINGLE_TOP,这是正确的,确保新Intent会触发onNewIntent而不是重新创建Activity)。
这样修改后,你的NfcManager封装就能正常工作,NFC标签扫描事件会正确触发MainActivity的onNewIntent方法。
内容的提问来源于stack exchange,提问作者Martin Denion




