Android读取信用卡等NFC卡片报文时无法识别部分类型卡片问题求助
问题核心原因
- NFC技术过滤器配置逻辑错误:
tech-list标签内的所有技术是同时满足的逻辑关系,你把所有NFC技术都放在同一个<tech-list>下,要求卡片必须同时支持Ndef、NfcA、NfcB、IsoDep、MifareClassic等全部9种技术,现实中没有这类卡片,所以除了刚好匹配到你之前的NDEF_DISCOVERED过滤器的公司卡片,其他卡都无法触发TECH_DISCOVERED回调。 - 部分配置冗余,且缺少前台NFC分发配置,容易被系统里其他NFC优先级更高的应用抢占卡片检测事件。
- 当前的NDEF_DISCOVERED过滤器仅覆盖text/plain类型和特定https链接的NDEF卡片,覆盖范围有限。
修复方案
第一步:修正nfc_tech_filter.xml配置
你需要把每一种要支持的技术单独放在一个<tech-list>标签下,代表满足任意一种技术即可匹配,修改后代码如下:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- 每个tech-list独立,满足其一即可匹配 --> <tech-list> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcA</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcF</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcV</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NdefFormatable</tech> </tech-list> <tech-list> <tech>android.nfc.tech.IsoDep</tech> </tech-list> <tech-list> <tech>android.nfc.tech.MifareClassic</tech> </tech-list> <tech-list> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> </resources>
信用卡、Oyster卡均支持IsoDep技术,修正后即可被TECH_DISCOVERED事件匹配到
第二步:优化AndroidManifest配置
移除application节点下冗余的com.google.android.actions meta-data配置,这个配置和NFC卡片检测无关,避免不必要的干扰。
第三步:添加前台NFC分发逻辑
Manifest配置的过滤器仅在应用后台时触发卡片跳转,应用在前台运行时,必须启用前台NFC分发,才能优先捕获NFC卡片事件,避免被其他应用抢占,核心代码示例如下:
private NfcAdapter nfcAdapter; private PendingIntent pendingIntent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); nfcAdapter = NfcAdapter.getDefaultAdapter(this); pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE); } @Override protected void onResume() { super.onResume(); // 前台时启用NFC分发,优先捕获事件 if (nfcAdapter != null && nfcAdapter.isEnabled()) { nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null); } } @Override protected void onPause() { super.onPause(); // 后台时停止前台分发 if (nfcAdapter != null) { nfcAdapter.disableForegroundDispatch(this); } } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); // 处理NFC卡片事件 String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // 后续处理卡片报文逻辑,IsoDep卡片可通过IsoDep.get(tag)获取对象进行通信 } }
内容的提问来源于stack exchange,提问作者kingston
相关产品推荐
相关产品推荐

