【发布时间】:2015-06-29 21:49:09
【问题描述】:
问题陈述
我试图了解为什么“选择 AID”命令并不总是成功路由到启用 HCE 的应用程序的 HostApduService。
有时,“Select AID”会正确路由到 HostApduService,从以下 logcat 输出可以看出:
07-11 20:11:36.386: D/NxpNfcJni(1486): RoutingManager::stackCallback: event=0x18
07-11 20:11:36.396: D/HostEmulationManager(1486): notifyHostEmulationActivated
07-11 20:11:36.396: D/NxpNfcJni(1486): RoutingManager::stackCallback: event=0x17
07-11 20:11:36.396: D/NxpNfcJni(1486): RoutingManager::stackCallback: NFA_CE_DATA_EVT; stat=0x0; h=0x301; data len=18
07-11 20:11:36.396: D/HostEmulationManager(1486): notifyHostEmulationData
07-11 20:11:36.396: D/HostEmulationManager(1486): Binding to service ComponentInfo{email.HCE/email.HCE.MyHCEService}
07-11 20:11:36.416: D/HostEmulationManager(1486): Waiting for new service.
07-11 20:11:36.466: D/MYHCESERVICE(25504): APDU RECEIVED
07-11 20:11:36.466: D/HostEmulationManager(1486): Sending data
07-11 20:11:37.276: E/SMD(284): DCD ON
07-11 20:11:37.436: D/NxpNfcJni(1486): RoutingManager::stackCallback: event=0x19
07-11 20:11:37.436: D/NxpNfcJni(1486): RoutingManager::stackCallback: NFA_DEACTIVATED_EVT, NFA_CE_DEACTIVATED_EVT
07-11 20:11:37.446: D/HostEmulationManager(1486): notifyHostEmulationDeactivated
07-11 20:11:37.446: D/MYHCESERVICE(25504): DISCONNECT
07-11 20:11:37.446: D/HostEmulationManager(1486): Unbinding from service ComponentInfo{email.HCE/email.HCE.MyHCEService}
07-11 20:11:37.446: D/MYHCESERVICE(25504): Disconnect by DEACTIVATION_LINK_LOSS
07-11 20:11:37.466: E/NfcNfa(1486): UICC/ESE[0x402] is not activated
但是,更频繁地,“选择 AID”命令似乎没有到达 HostApduService。更糟糕的是,在 LogCat 输出中似乎根本没有来自 NxpNfcJni 的活动。鉴于成功尝试的 LogCat 输出的摘录,我认为 NxpNfcJni 是入口点。
必须指出,成功的频率远低于失败的频率。
测试设置
以下是HCE设备的描述和相应的相关代码,后面是控制阅读器的应用程序的描述。
1. HCE 设备
- 硬件:三星 Galaxy S5
- 操作系统:Android 5.0
- HostApduService 的代码:
public class MyHCEService extends HostApduService {
@Override
public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
Log.d("MYHCESERVICE", "APDU RECEIVED");
return new byte[]{(byte)0x6F,(byte)0x25}; //returned byte array reduced for this example
}
@Override
public void onDeactivated(int reason) {
Log.d("MYHCESERVICE", "DISCONNECT");
switch(reason) {
case MyHCEService.DEACTIVATION_DESELECTED:
Log.d("MYHCESERVICE", "Disconnect by DEACTIVATION_DESELECTED");
case MyHCEService.DEACTIVATION_LINK_LOSS:
Log.d("MYHCESERVICE", "Disconnect by DEACTIVATION_LINK_LOSS");
}
}
}
- Android 清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="email.HCE"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyHCEService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice"/>
</service>
<activity
android:name=".ListBluetoothDevicesActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:configChanges="screenSize|orientation|keyboardHidden" >
</activity>
</application>
</manifest>
- AID 注册文件:
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc"
android:requireDeviceUnlock="false">
<aid-group android:description="@string/aiddescription"
android:category="other">
<aid-filter android:name="11223344556677889900112233"/>
</aid-group>
</host-apdu-service>
2。阅读器应用程序
- 非接触式读卡器:ASK RDR 417 http://ask-contactless.com/en-us/contactus/technicalsupport.aspx#gen4xx
- 基于 C# 的应用程序
- 使用PCSC-sharp 连接非接触式阅读器。
- 选择应用命令:
byte[] CMD_SelectApp = {
0x00, //CLA
0xA4, //INS
0x04, //P1
0x00, //P2
0x0D, //LC
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33 //AID
};
- 连接读卡器并发送选择应用命令的伪代码:
SCardContext _Context = new SCardContext();
_Context.Establish(SCardScope.System);
SCardReader _Reader = new SCardReader(_Context);
_Reader.Connect(SelectedReader, SCardShareMode.Direct, SCardProtocol.Any);
_Reader.Transmit(CMD_SelectApp, CMD_SelectApp.Length, RecvBuffer, ref ReceiveBufferLength);
问题
有人知道为什么“选择 AID”命令并不总是成功吗?或者有人可以给出一些指示来调试这个?
【问题讨论】:
-
对于不成功的 SELECT,您在阅读器端收到什么错误(或状态字)?
-
从 WinSCard.dll Transmit() 函数返回的错误代码是 1112d 或 0x0458。然而,这不是典型的 WinSCard 错误代码,因此在查看 Windows 错误时,这意味着:ERROR_NO_MEDIA_IN_DRIVE,来源:msdn.microsoft.com/en-us/library/windows/desktop/…