我知道这是一个没有明确答案的"讨论"主题,但我真的希望得到一些反馈,说明在开发适用于Android的NFC APP时会发生什么,特别是使用IsoDep使用APDU帧与DESFire卡进行通信.
我可以期望发送到特定DESFire卡的相同APDU帧在Android设备和版本中响应相同吗?
我应该测试哪些Android版本和设备至少要合理地覆盖?
Android驱动程序中的错误或回归是否常见,或者我可以预期这些问题在很久以前就已根除了?
您建议支持的最早版本的Android是什么,以避免太多麻烦?
到目前为止,我的经验令人惊讶地混合在一起(3个设备,3个不同),我真的希望听到其他开发人员的意见.例如:在S3(Android 4.1.2)上运行的相同APDU命令在S4(Android 4.3)上不起作用(第3次autenticate握手时"错误长度"失败,直到那时一切正常).这些手机有不同的NFC芯片组,但我没想到APDU帧的抽象级别存在差异.
这确实是一个讨论主题,但我认为它与Android NFC开发人员有关,因此我将在此处提供我的经验报告:
我可以期望发送到特定DESFire卡的相同APDU帧在Android设备和版本中响应相同吗?
是的,但仅适用于满足ISO/IEC 7816-4要求且具有一些额外限制的APDU命令(例如,并非所有设备都支持扩展长度的APDU,某些设备似乎存在案例1 APDU的问题).
最新版本的Broadcom NFC堆栈中也存在一些已知错误(见下文).
我应该测试哪些Android版本和设备至少要合理地覆盖?
到目前为止,我遇到的大多数问题都是带有Broadcom NFC芯片组的三星设备.虽然不是与APDU相关的,特别是在使用MIFARE Classic时,它们的行为与使用Broadcom芯片组的其他设备完全不同.例如,S4在系统级别阻止MIFARE Classic标签,因此不允许读取标签(N)UID.(无论如何,使用Broadcom芯片组都无法从MF Classic读取数据......)
关于测试,我建议每个NFC控制器至少使用一个Nexus设备(即一个配有NXP芯片组,一个配备Broadcom芯片组)和一个或两个其他手机制造商.(对于三星来说,配备NXP芯片组的设备与Nexus设备非常相似,所以我猜你是Nexus S/Galaxy Nexus,例如S3在NFC读写器模式体验方面可以看作是等效的.)
关于Android平台,我会坚持使用最多用户的平台.(还有那些卸载率很高的平台.)
Android驱动程序中的错误或回归是否常见,或者我可以预期这些问题在很久以前就已根除了?
正如我之前提到的那样,Broadcom NFC堆栈存在一些已知问题.特别是当涉及MIFARE DESFire时,存在一个已知问题,即NFC栈在将其传递给应用程序之后向卡发送任意基于APDU的命令.结果,那些命令可能干扰卡与该app之间的持续通信(例如,强制基于APDU的通信模式而不是本机命令模式,改变应用程序/文件选择等).有关更多详细信息,请参阅此错误报告和此stackoverflow问题.
通过错误跟踪器查看,肯定有更多未解决的问题.
您建议支持的最早版本的Android是什么,以避免太多麻烦?
关于基于APDU的通信(使用DESFire或其他卡),API 10(Android 2.3.3)及更高版本的工作正常.说到NFC API的可用性(除了简单的APDU交换)和漂亮的应用程序设计,我会坚持使用Android 4.0.3及更高版本.但请记住,最新的平台,特别是Android 4.3和Android 4.4引入了许多奇怪的行为/错误/("功能"?).
为了了解NFC设备目前拥有的Android版用户,我将分享NFC TagInfo的当前设备安装分发(尽管这可能略有偏差,因为NFC TagInfo不适合普通用户):
Android 4.1:36%
Android 4.3:21%
Android 4.2:19%
Android 4.4:18%
Android 4.0.3 - 4.0.4:4%
Android 2.3.3 - 2.3.7:2%
Android 4.0 - 4.0.2:0%
Android 3.2:0%
这个答案与您在一台设备上工作但未在其他设备上工作的APDU的具体问题有关.正如Michael Roland指出的那样,使用NCI NFC堆栈的设备经常发送可能会干扰应用程序发送的APDU的APDU.该问题与此堆栈中存在检查的错误实现有关,并在此处进行了说明.在DESFire卡上执行身份验证过程时尤其如此,因为它由多个APDU组成,如果被无关的APDU中断,则会失败.但是,在Android版本> = 4.4(API级别> = 19)上运行的设备有一种解决方法.在这些设备上,您可以使用带有EXTRA_READER_PRESENCE_CHECK_DELAY额外功能的enableReaderMode方法来配置状态检查的频率.通过增加延迟,您可以降低干扰应用程序APDU的可能性.
例如:
Bundle options = new Bundle(); options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 5000); getNfcAdapter().enableReaderMode( this, new ReaderCallback() { @Override public void onTagDiscovered(final Tag tag) { // ... authenticate ... } }, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, options);