1# HCE Development 2 3## Introduction 4Near Field Communication (NFC) is a short-range, high-frequency radio technology that operates at a frequency of 13.56 MHz, with a typical communication range of within 10 centimeters. Host Card Emulation (HCE) provides card emulation that does not depend on a secure element. It allows an application to emulate a card and communicate with an NFC card reader through the NFC service. 5 6## When to Use 7An application emulates a card and communicates with an NFC card reader through the NFC service. The device can communicate with an NFC card reader by using a started application (foreground mode) or without starting an application (background mode). 8- HCE foreground card swiping<br> 9In the foreground mode, the user has to start a specific application that communicates with the NFC card reader. Specifically, the user starts the application, opens the application page, and taps the device on the NFC card reader. In this case, the transaction data is distributed only to the foreground application. When the application switches to the background or exits, the foreground priority is also suspended. 10- HCE background card swiping<br> 11The user taps the device on an NFC card reader without starting any HCE application. Then, the device selects an HCE application based on the Applet ID (AID) provided by the NFC card reader, and completes the card swiping transaction. If multiple HCE applications are matched, an application selector will be displayed, listing all the available applications. In this case, the user needs to open the desired HCE application and tap the device on the NFC card reader again to trigger the card swiping transaction. 12 13## Constraints 141. For security reasons, regardless of whether the HCE application performs card swiping in the foreground or background, the device does not support HCE card swiping operations when it is in the screen-off state.<br> 152. A device must be equipped with an NFC controller chip to support HCE card swiping capabilities. There are no constraints on whether it has an NFC secure element.<br> 163. An HCE application must declare the NFC card emulation permission. For specific details, see the sample code.<br> 17 18## Available APIs 19 20For details about the APIs and sample code, [NFC Card Emulation](../../reference/apis-connectivity-kit/js-apis-cardEmulation.md). 21 22The following table describes the APIs for implementing HCE. 23 24| API | Description | 25| ---------------------------------- | ------------------------------------------------------------------------------ | 26| start(elementName: ElementName, aidList: string[]): void | Starts HCE, including enabling this application to run in the foreground preferentially and dynamically registering the AID list. | 27| stop(elementName: ElementName): void | Stops HCE, including canceling the subscription of APDU data, exiting this application from the foreground, and releasing the dynamically registered AID list. | 28| on(type: 'hceCmd', callback: AsyncCallback\<number[]>): void | Registers a callback to receive APDUs from the peer card reader. | 29| transmit(response: number[]): Promise\<void> | Transmits APDU data to the peer card reader.| 30| off(type: 'hceCmd', callback?: AsyncCallback\<number[]>): void| Unsubscribes from events indicating receiving of APDUs from the peer card reader.| 31 32## Preparations 33 34### Selecting Foreground or Background Card Swiping 35HCE application developers can choose to implement either foreground or background card swiping based on service requirements. These two methods differ in their code implementation. 36- HCE Foreground Card Swiping<br> 371. In the **module.json5** configuration file, there is no need to statically declare the AID selected by the NFC card reader. Instead, dynamically register an AID by using [start](../../reference/apis-connectivity-kit/js-apis-cardEmulation.md#start9). 382. When the card swiping page of the HCE application exits, explicitly called [stop](../../reference/apis-connectivity-kit/js-apis-cardEmulation.md#stop9) to release the dynamically registered AID. 39- HCE Background Card Swiping<br> 401. In the **module.json5** configuration file, statically declare the AID selected by the NFC card reader. Based on service requirements, specify whether the declared AID belongs to the **Payment** type or the **Other** type. 412. If the **Payment** type is selected, the HCE application will appear in the default payment app list on the NFC settings page. Users can only use background card swiping after selecting this HCE application as the default payment app. Since a default payment app is designated, there will be no conflicts between multiple HCE applications of the **Payment** type. 423. If the **Other** type is selected, the HCE application will not appear in the default payment app list on the NFC settings page. However, conflicts may arise if multiple HCE applications declare the same AID of the **Other** type. 434. When implementing HCE background card swiping, you do not need to call the **start** and **stop** APIs. 44 45> **NOTE** 46> 47> - Starting from API version 9, application development supports the Stage model, which is recommended for long-term evolution. 48> - All the HCE sample code in this document is based on the Stage model. 49 50## How to Develop 51 52### HCE Foreground Card Swiping 531. Declare the permission required for NFC card emulation and HCE action in the **module.json5** file. 542. Import modules. 553. Check whether the device supports the NFC and HCE capabilities. 564. Enable the foreground HCE application to preferentially process NFC card swiping. 575. Subscribe to the HCE APDU receiving events. 586. Receive and send APDU data for HCE card swiping. 597. Exit the HCE foreground mode when the application exits the NFC card swiping page. 60 61```ts 62 "abilities": [ 63 { 64 "name": "EntryAbility", 65 "srcEntry": "./ets/entryability/EntryAbility.ts", 66 "description": "$string:EntryAbility_desc", 67 "icon": "$media:icon", 68 "label": "$string:EntryAbility_label", 69 "startWindowIcon": "$media:icon", 70 "startWindowBackground": "$color:start_window_background", 71 "exported": true, 72 "skills": [ 73 { 74 "entities": [ 75 "entity.system.home" 76 ], 77 "actions": [ 78 "ohos.want.action.home", 79 80 // The **actions** field must contain ohos.nfc.cardemulation.action.HOST_APDU_SERVICE. 81 "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE" 82 ] 83 } 84 ] 85 } 86 ], 87 "requestPermissions": [ 88 { 89 // Add the permission required for NFC card emulation. 90 "name": "ohos.permission.NFC_CARD_EMULATION", 91 "reason": "$string:app_name", 92 } 93 ] 94``` 95 96```ts 97import { cardEmulation } from '@kit.ConnectivityKit'; 98import { BusinessError } from '@kit.BasicServicesKit'; 99import { hilog } from '@kit.PerformanceAnalysisKit'; 100import { AsyncCallback } from '@kit.BasicServicesKit'; 101import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; 102 103let hceElementName: bundleManager.ElementName; 104let hceService: cardEmulation.HceService; 105 106const hceCommandCb : AsyncCallback<number[]> = (error : BusinessError, hceCommand : number[]) => { 107 if (!error) { 108 if (hceCommand == null || hceCommand == undefined) { 109 hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.'); 110 return; 111 } 112 // The application checks the content of the received command and sends the matching response data based on its own service implementation. 113 hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand)); 114 let responseData = [0x90, 0x00]; // Change the response data based on the received command. 115 hceService.transmit(responseData).then(() => { 116 hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.'); 117 }).catch((err: BusinessError) => { 118 hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err)); 119 }); 120 } else { 121 hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error)); 122 } 123} 124 125export default class EntryAbility extends UIAbility { 126 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 127 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 128 129 // Check whether the device supports the NFC and HCE capabilities. 130 if (!canIUse("SystemCapability.Communication.NFC.Core")) { 131 hilog.error(0x0000, 'testTag', 'nfc unavailable.'); 132 return; 133 } 134 if (!cardEmulation.hasHceCapability()) { 135 hilog.error(0x0000, 'testTag', 'hce unavailable.'); 136 return; 137 } 138 139 // Initialize the correct value based on the application information. 140 hceElementName = { 141 bundleName: want.bundleName ?? '', 142 abilityName: want.abilityName ?? '', 143 moduleName: want.moduleName, 144 } 145 hceService = new cardEmulation.HceService(); 146 } 147 148 onForeground() { 149 // Switch the application to the foreground. 150 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); 151 if (hceElementName != undefined) { 152 try { 153 // Enable the foreground HCE application to preferentially process NFC card swiping. 154 let aidList = ["A0000000031010," "A0000000031011"]; // Set the AID list correctly. 155 hceService.start(hceElementName, aidList); 156 157 // Subscribe to the HCE APDU receiving events. 158 hceService.on('hceCmd', hceCommandCb); 159 } catch (error) { 160 hilog.error(0x0000, 'testTag', 'hceService.start error = %{public}s', JSON.stringify(error)); 161 } 162 } 163 } 164 165 onBackground() { 166 // Switch the application to the background. 167 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); 168 // When exiting the NFC tag page of the application, call the tag module API to exit the foreground mode. 169 if (hceElementName != undefined) { 170 try { 171 hceService.stop(hceElementName); 172 } catch (error) { 173 hilog.error(0x0000, 'testTag', 'hceService.stop error = %{public}s', JSON.stringify(error)); 174 } 175 } 176 } 177} 178``` 179 180### HCE Background Card Swiping 1811. Declare the permission required for NFC card emulation, HCE action, and AIDs for application matching in the **module.json5** file. 1822. Import modules. 1833. Check whether the device supports the NFC and HCE capabilities. 1844. Subscribe to the HCE APDU receiving events. 1855. Receive and send APDU data for HCE card swiping. 1866. Cancel the subscription when the application exits. 187 188```ts 189 "abilities": [ 190 { 191 "name": "EntryAbility", 192 "srcEntry": "./ets/entryability/EntryAbility.ts", 193 "description": "$string:EntryAbility_desc", 194 "icon": "$media:icon", 195 "label": "$string:EntryAbility_label", 196 "startWindowIcon": "$media:icon", 197 "startWindowBackground": "$color:start_window_background", 198 "exported": true, 199 "skills": [ 200 { 201 "entities": [ 202 "entity.system.home" 203 ], 204 "actions": [ 205 "ohos.want.action.home", 206 207 // The **actions** field must contain ohos.nfc.cardemulation.action.HOST_APDU_SERVICE. 208 "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE" 209 ] 210 } 211 ], 212 213 // Define at least one AID of the Payment or Other type based on service requirements. 214 "metadata": [ 215 { 216 "name": "payment-aid", 217 "value": "A0000000031010" // Define the AID of the Payment type. 218 }, 219 { 220 "name": "other-aid", 221 "value": "A0000000031011" // Define the AID of the Other type. 222 } 223 ] 224 } 225 ], 226 "requestPermissions": [ 227 { 228 // Add the permission required for NFC card emulation. 229 "name": "ohos.permission.NFC_CARD_EMULATION", 230 "reason": "$string:app_name", 231 } 232 ] 233``` 234 235```ts 236import { cardEmulation } from '@kit.ConnectivityKit'; 237import { BusinessError } from '@kit.BasicServicesKit'; 238import { hilog } from '@kit.PerformanceAnalysisKit'; 239import { AsyncCallback } from '@kit.BasicServicesKit'; 240import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; 241 242let hceElementName : bundleManager.ElementName; 243let hceService: cardEmulation.HceService; 244 245const hceCommandCb : AsyncCallback<number[]> = (error : BusinessError, hceCommand : number[]) => { 246 if (!error) { 247 if (hceCommand == null || hceCommand == undefined) { 248 hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.'); 249 return; 250 } 251 252 // The application checks the content of the received command and sends the matching response based on its own service implementation. 253 hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand)); 254 let responseData = [0x90, 0x00]; // Change the response data based on the received command. 255 hceService.transmit(responseData).then(() => { 256 hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.'); 257 }).catch((err: BusinessError) => { 258 hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err)); 259 }); 260 } else { 261 hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error)); 262 } 263} 264 265export default class EntryAbility extends UIAbility { 266 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 267 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 268 269 // Check whether the device supports the NFC and HCE capabilities. 270 if (!canIUse("SystemCapability.Communication.NFC.Core")) { 271 hilog.error(0x0000, 'testTag', 'nfc unavailable.'); 272 return; 273 } 274 if (!cardEmulation.hasHceCapability()) { 275 hilog.error(0x0000, 'testTag', 'hce unavailable.'); 276 return; 277 } 278 279 // Subscribe to HCE card swiping data when the application is running in the foreground. 280 hceService = new cardEmulation.HceService(); 281 hceService.on('hceCmd', hceCommandCb); 282 } 283 284 onForeground() { 285 // Switch the application to the foreground. 286 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); 287 } 288 289 onDestroy() { 290 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); 291 // Unsubscribe from HCE card swiping data when the application exits. 292 hceService.off('hceCmd', hceCommandCb); 293 } 294} 295``` 296