Search code examples
androidnfcsmartcardhcecontactless-smartcard

Android: HCE of 14443 type A card


I'm trying to develop an application that uses Android NFC as smart card (Android 4.4.2 in HCE mode). I've read the guide about HCE on Android 4.4. I used the example along with the Android 4.4 SDK. But if try to read the HCE-emulated smart card from another Android NFC device (Android 4.3) with an NFC reader application, I see only these logs:

03-31 17:02:21.151: I/NFC-HCI(600): I'm P2P Active Initiator @ 424 kb/s
03-31 17:02:21.159: D/NFCJNI(600): Discovered P2P Target
03-31 17:02:21.159: D/NfcService(600): LLCP Activation message
03-31 17:02:21.183: I/NFC-HCI(600): I'm P2P Active Initiator @ 424 kb/s
03-31 17:02:21.190: I/NFCJNI(600): LLCP Link activated (LTO=150, MIU=128, OPTION=0x00, WKS=0x13)
03-31 17:02:21.190: I/NfcP2pLinkManager(600): LLCP activated
03-31 17:02:21.190: D/NfcP2pLinkManager(600): onP2pInRange()
[...]
03-31 17:02:22.144: I/NFCJNI(600): LLCP Link deactivated
03-31 17:02:22.144: D/NfcService(600): LLCP Link Deactivated message. Restart polling loop.
03-31 17:02:22.144: I/NfcP2pLinkManager(600): LLCP deactivated.
03-31 17:02:22.144: D/NfcP2pLinkManager(600): Debounce timeout
03-31 17:02:22.151: D/NfcP2pLinkManager(600): onP2pOutOfRange()

If I try, instead, to read a real smart card, it works as expected and I'm able to read the card:

TagID (hex): c4 2a 29 c8
TagID (dec): 3291097544
Technologies: MifareClassic, NfcA,NdefFormatable
Mifare Classic type: Classic
Mifare size: 1024 btes
Mifare sectors: 16
Mifare blocks: 64

I've read this thread but my knowledge in this regard are very few.


Solution

  • Simple answer: what you are trying to do is not possible.

    The problem here is that two Android devices will communicate in peer-to-peer mode by default (even if one or both devices support host card emulation). Once an Android device successfully communicates in peer-to-peer mode, it won't try to communicate in reader/writer mode. Consequently, your device with the reader app won't detect the HCE-emulated "card" of the other device.

    In order to permit the Android HCE-emulated card to be visible to the second device with the reader app, that second device would need to disable its peer-to-peer mode capabilities and be active only in reader/writer mode. That's were the thread you were refereing to (Android : How to change NFC protocol priority?) comes in. By using the reader mode API, more specifically the enableReaderMode method of the NfcAdapter with the flags FLAG_READER_NFC_A, FLAG_READER_NFC_B (and optionally FLAG_READER_SKIP_NDEF_CHECK), you can force the (reader side!!!) Android device to act only in reader/writer mode and to disable peer-to-peer mode:

    NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    nfcAdapter.enableReaderMode(this, new NfcAdapter.ReaderCallback() {
        public void onTagDiscovered(Tag tag) {
            // TODO: access tag...
        }
    },
    NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null);
    

    Unfortunately, this API is only available on Android 4.4 and later. So with an Android 4.3 device, you have no means to disable peer-to-peer mode and therefore can't communicate with an Android HCE "card".