读取Android NFC IsoDep标签时出现连接错误

8

我有一个读取各种类型NFC标签的应用程序。多年来一直都很正常,但是在较新的Android设备上扫描特定类型的标签时会始终抛出java.io.IOException异常。这个标签支持Mifare Classic和ISO-DEP,但我们是使用IsoDep技术进行连接。

NFC TagInfoNFC TagInfo by NXP 应用程序也无法无错地读取此标签。


可用设备:

  • Moto X Play(Android 6.0.1)
  • Moto G Play(Android 6.0.1)
  • Samsung Galaxy S7(Android 7.0)
  • Samsung Galaxy S8 - 英国版(Android 7.0)
  • Pixel 2(Android 8.1)

不可用设备:

  • Moto G5S(Android 7.1.1)
  • Moto Z2 Play(Android 7.1.1)
  • Moto E4 Plus(Android 7.1.1)
  • Huawei Honor 8(Android 7.0)
  • LG K8(Android 7.0)
  • LG K10(Android 7.0)
  • Samsung Galaxy S8 - 美国版(Android 7.0)

需要重现问题的代码非常简单。

NFC意图通过前台调度接收,然后在自己的线程中运行以下内容(没有其他线程或NFC相关处理):

IsoDep isoDep = IsoDep.get(tag);

try {
    isoDep.connect();
}
catch (IOException e) {
    Log.e("NFC", ":(");
}

android.nfc.tech.BasicTagTechnology中的connect()方法抛出IOException时,errorCode为-5(ERROR_CONNECT)。
有趣的是,对于正常工作的设备,Tag公开的技术列表如下:android.nfc.tech.IsoDep,android.nfc.tech.NfcA 对于不工作的设备,技术列表要长得多,并且包含重复项:android.nfc.tech.IsoDep,android.nfc.tech.NfcA,android.nfc.tech.NfcA,android.nfc.tech.MifareClassic,android.nfc.tech.NdefFormattable 最后,对于不工作的设备,在logcat中出现以下条目:E/NxpNfcJni: Mifare Classic detected 是否可能由于更现代的Android设备提供了扩展的NFC支持,导致NFC系统服务内部混淆了要连接的TagTechnology?

你找到解决这个问题的方法了吗? - Nikoloz
@Nikoloz 是的,我们做到了。我们在Android应用程序中用代码尝试了所有可能的方法,但最终不得不找到一个解决方法。我不知道具体细节,但解决方案是通过删除其中一种技术类型来简化NFC标签,这样应用程序就不需要做出任何关于使用哪种技术的决定。如果需要,我可以尝试获取更具体的信息。 - Jay
@Jay,你能提供更多细节吗? - Roman Svyatnenko
很抱歉,我不知道。我之前离开了这个组织,并且当时并没有积极参与NFC方面的修复工作。对不起。 - Jay
有人找到答案了吗?我也遇到了同样的问题。 - Prashant.J
2个回答

0
当一个标签支持多个技术条目时,每个条目可以使用基本的标签技术API - tag.getTechList()进行独立访问。
请按以下方式修改您的代码:
    techList =  tag.getTechList();
    for (String tech : techList) {
        if (tech.equals("android.nfc.tech.IsoDep")) 
        {
            Log.i(TAG, "Tag Tech ISO DEP Found: " + tech );
            IsoDep isoDep = IsoDep.get(tag);
            try 
            {
                    isoDep.connect();
            }
            catch (IOException e) 
            {
                Log.e("NFC", ":(");
            }
        }
    }

并非所有设备都支持MifareClassic标签技术。


0

当我在 Android 8+ 和 Android 6、7 上进行测试时,发现使用 IsoDep 类时出现了类似的问题。

对我来说,关键是利用 NfcAdapter.enableReaderMode 实例方法,在我的应用程序前台尝试读取/写入标签时关闭 Android 设备上的 Host-Card-Emulation

然后,我没有像 文档示例 中所示那样应用生命周期回调,而是按照这个 问题 中提到的建议进行操作:

@Override
public void onPause() {
    super.onPause();
    NfcAdapter.getDefaultAdapter(this).disableReaderMode(this);
}

@Override
public void onResume() {
    super.onResume();

    Bundle options = new Bundle();
    options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 500);

    adapter.enableReaderMode(
        this,
        new NfcAdapter.ReaderCallback() {
             @Override
             public void onTagDiscovered(final Tag tag) {
                 IsoDep isoDep = IsoDep.get(tag);
                 // Connect and perform rest of communication
             }
        },
        NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK,
        options
    ); 
}

@Override
public void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接