{"id":24501091,"url":"https://github.com/androidcrypto/android_hce_beginner_app","last_synced_at":"2025-04-14T05:42:37.811Z","repository":{"id":255674634,"uuid":"853377744","full_name":"AndroidCrypto/Android_HCE_Beginner_App","owner":"AndroidCrypto","description":"The app includes a Host-Based Card Emulated (HCE) NFC tag and the associated NFC reader. You learn how to setup your own HCE application and how you can communicate with the HCE tag. A tutorial is available on medium.com for more informations.","archived":false,"fork":false,"pushed_at":"2025-01-07T10:59:39.000Z","size":13584,"stargazers_count":15,"open_issues_count":3,"forks_count":7,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-27T19:40:40.921Z","etag":null,"topics":["android","hce","nfc","nfc-reader","nfc-reader-and-writer","nfc-writer","tutorial","tutorial-code"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AndroidCrypto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-06T14:34:58.000Z","updated_at":"2025-03-27T00:15:21.000Z","dependencies_parsed_at":"2025-01-07T11:35:24.942Z","dependency_job_id":"8a599a30-8280-40d9-9bb8-f88e2b8becb1","html_url":"https://github.com/AndroidCrypto/Android_HCE_Beginner_App","commit_stats":null,"previous_names":["androidcrypto/android_hce_beginner_app"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndroidCrypto%2FAndroid_HCE_Beginner_App","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndroidCrypto%2FAndroid_HCE_Beginner_App/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndroidCrypto%2FAndroid_HCE_Beginner_App/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndroidCrypto%2FAndroid_HCE_Beginner_App/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AndroidCrypto","download_url":"https://codeload.github.com/AndroidCrypto/Android_HCE_Beginner_App/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248830420,"owners_count":21168272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","hce","nfc","nfc-reader","nfc-reader-and-writer","nfc-writer","tutorial","tutorial-code"],"created_at":"2025-01-21T22:23:16.163Z","updated_at":"2025-04-14T05:42:37.785Z","avatar_url":"https://github.com/AndroidCrypto.png","language":"Java","readme":"# Android HCE Beginner App\n\n## Host-based card emulation overview\n\nI will quote a lot of times from this official document, see the full document here: \nhttps://developer.android.com/develop/connectivity/nfc/hce\n\n*Android 4.4 and higher provide an additional method of **card emulation** that doesn't involve a secure element, \ncalled **host-based card emulation**. This allows any Android application to emulate a card and talk directly \nto the NFC reader. This topic describes how host-based card emulation (**HCE**) works on Android and how you \ncan develop an app that emulates an NFC card using this technique.*\n\n## Purpose of this App\n\nThis app explains how to setup an application that runs the **Host-Based Card Emulation (HCE)** feature on an \nAndroid device. I'm describing step by step what requirements are to meet to transfer some very simple data. \n**There will be no special features like emulating a complete NFC card**, but in the end you will understand what the \nsteps are to write your own app.\n\nThis repository is accompanied by a tutorial on medium.com, please find the article here: https://medium.com/@androidcrypto/how-to-use-host-based-card-emulation-hce-in-android-a-beginner-tutorial-java-32974dd89529\n\n## Requirements to follow the tutorial\n\nAs our Android device will act as a real NFC tag, you will need a **second NFC-Reader** (e.g. a second Android device) to run the tests, \nbecause when an Android device is in HCE mode it cannot read \"itself\" (on the same device). Unfortunately, not all Android devices, \neven with an NFC reader, are enabled for HCE, so you need to check that your device is capable to run HCE. You can run a simple check \nusing \"**FEATURE_NFC_HOST_CARD_EMULATION**\" to verify that you can run HCE. \n\nThe minimum SDK version for this app is Android 5 (SDK 21), and your device needs to have an NFC reader on board.\n\nThis app is developed using Android Studio 2024.1.1 and I'm using the Java Runtime version: 17.0.11+0-17.0.11b1207.24-11852314 aarch64 \non MacOS/Silicon.\n\n## Most important facts\n\n### Application Identifier (AID)\n\nI'm receiving a lot of questions like *\"why does my HCE implementation does not work and is not recognized by another device ?\"*. \nIn most of the cases the reason for the failure is that both devices use a different **Application Identifier\" (\"**AID**\"). In the \nend, that means they speak \"different languages\" and don't understand each other.\n\nFrom Wikipedia: *An application identifier (AID) is used to address an application in the card or Host Card Emulation (HCE) if \ndelivered without a card. An AID consists of a registered application provider identifier (RID) of five bytes, which is issued \nby the ISO/IEC 7816-5 registration authority. This is followed by a proprietary application identifier extension (PIX), which \nenables the application provider to differentiate among the different applications offered. The AID is printed on all EMV \ncardholder receipts. Card issuers can alter the application name from the name of the card network.*\n\n**Registered Application Identifier**: You cannot choose an Application identifier (AID) on your own because then you may get \ntrouble when working with established reader infrastructure. There are three groups of AIDs:\n- Category \"A\": That are international registered AIDs, mainly for Payment Provider like Mastercard or Visa Card. Please don't choose an AID from this category !\n- Category \"D\": That are national registered AIDs, e.g. for Payment Provider like local bank cards or for accessing NFC tags. Please don't choose an AID from this category !\n- Category \"F\": That are proprietary (non registered) AIDs, e.g. for this application.\n\nPlease find a very extensive list of existing AID's for payment cards here: https://www.eftlab.com/knowledge-base/complete-list-of-application-identifiers-aid\n\nPlease do not use AIDs with a length less than 5 as they won't get routed on Android devices properly. The maximum length of \nan AID is 16 bytes (see https://stackoverflow.com/a/27620724/8166854 for more details).\n\nThis app uses the AID **F22334455667**.\n\n### Run a HCE services in the background\n\nMost people believe, that the emulated tag is run by your app, but that is not true. Of course, you need to run an app for the first \ntime to start a (HCE) service in the background, but from now on all communication is done **between your service and the remote NFC reader**. \nYour app will get no further updates about the communication or and information that data is exchanged. You need to implement \nan interface to get informed about any updates. For that reason it not very easy to monitor your running app from \"inside\" your app.\n\nYour app will still persistent to work, even when you close your app with the Android Taskmanager - because it is a service.\n\n### Payment and other applications\n\nIf you are running the Google Wallet app on your device you know that your device is HCE capable, because Google Wallet emulates a \n**Payment Card** (like Credit Cards). Those applications are called **Payment applications** and usually a device should run only one payment \napplication for emulating. For that reason we will design our app as \"other application\" HCE type to avoid any conflicts with existing \npayment apps.\n\n### HCE and security\n\nFrom the documentation: *The HCE architecture provides one core piece of security: because your service is protected by the **BIND_NFC_SERVICE** \nsystem permission, only the OS can bind to and communicate with your service. This ensures that any APDU you receive is actually an APDU that \nwas received by the OS from the NFC controller, and that any APDU you send back only goes to the OS, which in turn directly forwards the APDUs \nto the NFC controller.*\n\n*The last remaining concern is where you get your data that your app sends to the NFC reader. This is intentionally decoupled in the HCE design; \nit does not care where the data comes from, it just makes sure that it is safely transported to the NFC controller and out to the NFC reader.*\n\n*For securely storing and retrieving the data that you want to send from your HCE service, you can, for example, rely on the Android Application \nSandbox, which isolates your app's data from other apps. For more details about Android security, read Security tips \n(https://developer.android.com/training/articles/security-tips).* \n\n### What is the application protocol data unit (APDU) ?\n\nYou will notice that \"**APDU**\" is written in many tutorials and source codes. The APDU protocol is the way how an NFC-Reader and NFC-Smart Card are \ngoing to communicate, it is an **APDU message command-response pair**, consisting of two pieces:\n\na) The NFC-Reader is sending data by sending a **command APDU** to the NFC Smart Card\n\nb) The  NFC Smart Card answers the  command by sending a **response APDU** to the NFC Reader.\n\nIn our case, our HCE app needs to response to a command APDU as our app is acting like a real NFC Smart Card. As each NFC Smartcard follows a card \nspecific protocol it is important that our HCE app acts like the same. If not - the real NFC Reader will think \"that is not the NFC tag I expected\" \nand will stop any further communication with out app.\n\n### ISO 7816-4 Section 6 - Basic Interindustry Commands\n\nTo understand the commands between an NFC reader and a tag (real or emulated one) you should get familiar with the ISO 7816-4 commands. \nIn this tutorial I'm using just 3 of them:\n\n**SELECT APPLICATION APDU**: The \"Select Application\" APDU is the starting point for every communication with an emulated (HCE driven) NFC tag. \nIf you miss to send this command your HCE tag won't recognize the request and will not answer or react in any way. The second fact is: as I'm \nusing a proprietary AID for this app an NFC reader like the TagInfo app by NXP does not know about this specific AID you cannot read the HCE \ntag with regular NFC reader apps. The \"Select Application APDU\" for the HCE emulated tag of the Beginner App is \"00A4040006F2233445566700h\". \nTo understand the response see the chapter APDU Responses.\n\n**GET DATA APDU**: The \"Get Data\" APDU is used to request data from the tag. In most more complex NFC tags the data is organized within files \nlike the one you know from your home computer. The file system is organized by using file numbers that are part of the command:\n\n```vplaintext \nGet Data APDU: 00ca0000010100\nI'm splitting the bytes into their meaning (all data are hex encoded):\n\n00: CLA = Class of instruction, length 1 byte, the start of the command sequence\nCA: INS = Instruction, length 1 byte, is the GET DATA command\n00: P 1 = Selection Control 1, length 1 byte, in range '0000'-'003F' it is RFU\n00: P 2 = Selection Control 2, length 1 byte, in range '0000'-'003F' it is RFU\n01: LC Field: Length of the following data, length 1 byte, number of following data bytes\n01: Data: Data send together with the command, here the 1 byte long file number\n00: Le field: Empty or maximum length of data expected in response\n```\nThe \"Get Data\" APDU for reading the content of file 01 from the HCE emulated tag of the Beginner App is \"00ca0000010100h\". To understand \nthe response see the chapter APDU Responses.\n\n**PUT DATA APDU**: The \"Put Data\" APDU is used to send data to the tag. In most more complex NFC tags the data is organized within files \nlike the one you know from your home computer. The file system is organized by using file numbers that are part of the command, together \nwith data that gets stored:\n\n```plaintext\nPUT DATA APDU: 00da00001d024e65..303200\nI'm splitting the bytes into their meaning (all data are hex encoded):\n\n00: CLA = Class of instruction, length 1 byte, the start of the command sequence\nDA: INS = Instruction, length 1 byte, is the PUT DATA command\n00: P 1 = Selection Control 1, length 1 byte, in range '0000'-'003F' it is RFU\n00: P 2 = Selection Control 2, length 1 byte, in range '0000'-'003F' it is RFU\n1d: LC Field: Length of the following data, length 1 byte, number of following data bytes\n1dh = 29 bytes of data following\n01: Data: Data send together with the command, here the 1 byte long file number (here file 02)\n4e65..3032: Data: Data send together with the command, here the 28 bytes long data\n00: Le field: Empty or maximum length of data expected in response\n```\n\nIn this command the data consists of 2 single data fields the 1 byte long file number and the data (here 28 bytes). I'm sending this string:\n\n```plaintext\ndataToWrite in UTF-8 encoding: New Content in fileNumber 02\ndataToWrite in hex encoding: 4e657720436f6e74656e7420696e2066696c654e756d626572203032\n```\nThe \"PUT DATA\" APDU for the HCE emulated tag of the Beginner App is \"00da00001d024e657720436f6e74656e7420696e2066696c654e756d62657220303200h\". \nTo understand the response see the chapter APDU Responses.\n\n**APDU Responses**: To understand the APDU response we need to divide all commands in one of the two categories:\n\n- send the command only or send the command together with data (e.g. PUT DATA APDU)\n- send the command (together with specifying parameter like the file number) and receive data in return (e.g. GET DATA APDU).\n\n- Send the command only or with data: If the card accepts the command it simply answers with a 2 bytes long code: \"9000h\":\n\n```plaintext \nOK-Response: 9000h\n90 = SW 1 = Status byte 1 = Command processing status\n00 = SW 2 = Status byte 2 = Command processing qualifier\n```\n\nIf the bytes are \"9000h\" the command was \"Accepted\". Every other response should be treated as \"Not Accepted\". The ISO can define a more \nspecified response for different cases, but in our case we just check for \"9000h\" or not \"9000h\".\n \n- Send the command and receive data in return: In this case the returned data is a little bit different. In case of command acceptance we \n- receive the data, concatenated with the two Status bytes. This is the sample response to the \"Get Data\" APDU:\n\n```plaintext \nGet Data APDU: 00ca0000010100\nResponse: 48434520426567696e6e65722041707020319000\nThe complete response is 20 bytes long:\nData (18 bytes):  48434520426567696e6e6572204170702031\nStatus Bytes 1+2: 9000\nThe Data is this String: HCE Beginner App 1\n```\n\nIn case of success we get the data, followed by the 2 bytes long Status bytes. In case of failure (e.g. wrong command length) the tag answers \nwith \"0000h\". The Beginner app knows a third response case: in case the file number does not exist (e.g. file number 3) the tag is returning \nthe string \"HCE Beginner App Unknown\", followed by the OK-Status bytes \"9000h\". Every other response should be treated as \"Not Accepted\". The \nISO can define a more specified response for different cases, but in our case we just check for \"9000h\" or not \"9000h\".\n\nFor more details about ABDU's see: https://cardwerk.com/smart-card-standard-iso7816-4-section-6-basic-interindustry-commands/\n\nPUT DATA command\n```plaintext\nPUT DATA command APDU\nCLA\t        00h\nINS\t        DAh\nP1          00h\nP2\t        00h\nLc field\tLength of the subsequent data field\nData field\tParameters and data to be written\nLe field\tEmpty\n```\n\n## UID of an emulated NFC tag\n\nIf you run my app you will notice that I'm exposing the tag UID in the Logfile within the Reader app. This \n**UID is exact 4 bytes long and random**. This is a security feature to prevent privacy to the user - this \nway a large NFC reader infrastructure (think of a \"Smart City\" with hundreds of NFC readers) is not being \nable to track a user (better: his NFC card). There is no workaround to change the behaviour of a modern \nAndroid device to get a static UID each time you tap the emulated tag to an NFC reader, sorry.\n\nThe only way would be to store the UID in a \"read only\" file on the tag to get a unambiguously tag identification.\n\n## Steps to create a HCE application\n\nThese are the basic steps you need to implement a HCE application on your device:\n\n1) Create a HCE service class that is extending the **HostApduService**\n2) Register your HCE service in **AndroidManifest.xml**\n3) Create an **XML-file in your resources** that defines the application identifier your HCE application in working on (\"apduservice.xml\")\n4) Register the XML-file in **AndroidManifest.xml** to link the AID with your own HCE service\n\n**That's all ?** - yes we don't need more steps to build a HCE application.\n\n## Example output\n\n```plaintext\nTagId: 08ca20a8\nselectApdu with AID: 00a4040006f2233445566700\nselectApdu response: 0000\nresponse length: 2 data: 0000\ngetDataApdu with file01: 00ca0000010100\nresponse length: 20 data: 48434520426567696e6e65722041707020319000\nHCE Beginner App 1\ngetDataApdu with file02: 00ca0000010200\nresponse length: 20 data: 48434520426567696e6e65722041707020329000\nHCE Beginner App 2\nputDataApdu with file02: 00da00001d024e657720436f6e74656e7420696e2066696c654e756d62657220303200\nresponse length: 2 data: 9000\nSUCCESS\ngetDataApdu with file02: 00ca0000010200\nresponse length: 30 data: 4e657720436f6e74656e7420696e2066696c654e756d6265722030329000\nNew Content in fileNumber 02\n```\n\n## Some data regarding  the reader application\n\nThe NFC reader application is designed to communicate with the HCE emulated tag. It will probably not work \nwith other (real or emulated) NFC tags as it uses a static, proprietary Application Identifier (\"F22334455667\").\n\nThe reader is following this workflow:\n\n- connect to the HCE tag by sending the **Select Application APDU** command\n- send the **Get Data APDU** command to retrieve the content of file number 01 on the HCE tag\n- send the **Get Data APDU** command to retrieve the content of file number 02 on the HCE tag\n- send the **Put Data APDU** command to write a new string on file number 02 on the HCE tag\n- send the **Get Data APDU** command to retrieve the new content of file number 02 on the HCE tag\n- EOC - End of Communication\n\nLatest update: Sep. 18.th, 2024\n\n## License\n\nAndroid HCE Beginner Appis available under the MIT license. See the LICENSE.md file for more info.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandroidcrypto%2Fandroid_hce_beginner_app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandroidcrypto%2Fandroid_hce_beginner_app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandroidcrypto%2Fandroid_hce_beginner_app/lists"}