1# HCE Development 2 3## Introduction 4Near Field Communication (NFC) is a high-frequency radio technology that enables communication between devices over a distance less than 10 cm. NFC operates at 13.56 MHz. 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 mode 9 10 The application started by the user 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. 11 12- HCE background mode 13 14 The user taps the device on an NFC card reader without starting any HCE application. Then, the device selects an HCE application based on the application 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 for the user to choose. 15 16- Constraints 17 18 No matter whether the foreground mode or background mode is used, the NFC service can be implemented only when the device screen is unlocked and illuminated. 19 20 The permission for NFC card emulation must be declared in the **module.json5** file. For details, see the example below. 21 22 The foreground application needs to call **start()** to register AIDs and call **stop()** to release the registered AIDs. For details, see the example below. 23 24## Available APIs 25 26For details about the JS APIs and sample code, [NFC Card Emulation](../../reference/apis-connectivity-kit/js-apis-cardEmulation.md). 27 28The following table describes the APIs for implementing HCE. 29 30| API | Description | 31| ---------------------------------- | ------------------------------------------------------------------------------ | 32| start(elementName: ElementName, aidList: string[]): void | Starts HCE, including enabling this application to run in the foreground preferentially and dynamically registering the AID list. | 33| 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.| 34| on(type: 'hceCmd', callback: AsyncCallback\<number[]>): void | Registers a callback to receive APDUs from the peer card reader.| 35| transmit(response: number[]): Promise\<void> | Transmits APDU data to the peer card reader.| | 36 37## How to Develop 38 39### HCE Foreground Mode 401. Declare the permission required for NFC card emulation and HCE action in the **module.json5** file. 412. Import modules. 423. Check whether the device supports the NFC and HCE capabilities. 434. Enable the foreground HCE application to preferentially process NFC card swiping. 445. Subscribe to the reception of HCE APDU data. 456. Receive and send APDU data for HCE card swiping. 467. Exit the HCE foreground mode when the application exits the NFC card swiping page. 47 48```ts 49 "abilities": [ 50 { 51 "name": "EntryAbility", 52 "srcEntry": "./ets/entryability/EntryAbility.ts", 53 "description": "$string:EntryAbility_desc", 54 "icon": "$media:icon", 55 "label": "$string:EntryAbility_label", 56 "startWindowIcon": "$media:icon", 57 "startWindowBackground": "$color:start_window_background", 58 "exported": true, 59 "skills": [ 60 { 61 "entities": [ 62 "entity.system.home" 63 ], 64 "actions": [ 65 "action.system.home", 66 67 // Add the nfc card emulation action to filter out for this application. 68 "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE" 69 ] 70 } 71 ] 72 } 73 ], 74 "requestPermissions": [ 75 { 76 // Add the permission for nfc card emulation. 77 "name": "ohos.permission.NFC_CARD_EMULATION", 78 "reason": "$string:app_name", 79 } 80 ] 81``` 82 83```ts 84import { cardEmulation } from '@kit.ConnectivityKit'; 85import { BusinessError } from '@kit.BasicServicesKit'; 86import { hilog } from '@kit.PerformanceAnalysisKit'; 87import { AsyncCallback } from '@kit.BasicServicesKit'; 88import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; 89 90let hceElementName: bundleManager.ElementName; 91let hceService: cardEmulation.HceService; 92 93const hceCommandCb : AsyncCallback<number[]> = (error : BusinessError, hceCommand : number[]) => { 94 if (!error) { 95 if (hceCommand == null || hceCommand == undefined) { 96 hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.'); 97 return; 98 } 99 // check the command, then transmit the response. 100 hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand)); 101 let responseData = [0x90, 0x00]; // change the response depend on different received command. 102 hceService.transmit(responseData).then(() => { 103 hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.'); 104 }).catch((err: BusinessError) => { 105 hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err)); 106 }); 107 } else { 108 hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error)); 109 } 110} 111 112export default class EntryAbility extends UIAbility { 113 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 114 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 115 116 // Check whether the device supports the NFC and HCE capabilities. 117 if (!canIUse("SystemCapability.Communication.NFC.Core")) { 118 hilog.error(0x0000, 'testTag', 'nfc unavailable.'); 119 return; 120 } 121 if (!cardEmulation.hasHceCapability()) { 122 hilog.error(0x0000, 'testTag', 'hce unavailable.'); 123 return; 124 } 125 126 hceElementName = { 127 bundleName: want.bundleName ?? '', 128 abilityName: want.abilityName ?? '', 129 moduleName: want.moduleName, 130 } 131 hceService = new cardEmulation.HceService(); 132 } 133 134 onForeground() { 135 // Ability is brought to foreground. 136 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); 137 if (hceElementName != undefined) { 138 try { 139 // Enable the foreground HCE application to preferentially process NFC card swiping. 140 let aidList = ["A0000000031010", "A0000000031011"]; // Change the AIDs to match your case. 141 hceService.start(hceElementName, aidList); 142 143 // Subscribe to the reception of HCE APDU data. 144 hceService.on('hceCmd', hceCommandCb); 145 } catch (error) { 146 hilog.error(0x0000, 'testTag', 'hceService.start error = %{public}s', JSON.stringify(error)); 147 } 148 } 149 } 150 151 onBackground() { 152 // Ability is in the background. 153 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); 154 // When exiting the NFC tag page of the application, call the tag module API to exit the foreground mode. 155 if (hceElementName != undefined) { 156 try { 157 hceService.stop(hceElementName); 158 } catch (error) { 159 hilog.error(0x0000, 'testTag', 'hceService.stop error = %{public}s', JSON.stringify(error)); 160 } 161 } 162 } 163} 164``` 165 166### HCE Background Mode 1671. Declare the permission required for NFC card emulation, HCE action, and AIDs for application matching in the **module.json5** file. 1682. Import modules. 1693. Check whether the device supports the NFC and HCE capabilities. 1704. Subscribe to the reception of HCE APDU data. 1715. Receive and send APDU data for HCE card swiping. 1726. Cancel the subscription when the application exits. 173 174```ts 175 "abilities": [ 176 { 177 "name": "EntryAbility", 178 "srcEntry": "./ets/entryability/EntryAbility.ts", 179 "description": "$string:EntryAbility_desc", 180 "icon": "$media:icon", 181 "label": "$string:EntryAbility_label", 182 "startWindowIcon": "$media:icon", 183 "startWindowBackground": "$color:start_window_background", 184 "exported": true, 185 "skills": [ 186 { 187 "entities": [ 188 "entity.system.home" 189 ], 190 "actions": [ 191 "action.system.home", 192 193 // Add the nfc card emulation action to filter out for this application. 194 "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE" 195 ] 196 } 197 ], 198 "metadata": [ 199 { 200 "name": "payment-aid", 201 "value": "A0000000031010" // change it tobe correct 202 }, 203 { 204 "name": "other-aid", 205 "value": "A0000000031011" // change it tobe correct 206 } 207 ] 208 } 209 ], 210 "requestPermissions": [ 211 { 212 // Add the permission for nfc card emulation. 213 "name": "ohos.permission.NFC_CARD_EMULATION", 214 "reason": "$string:app_name", 215 } 216 ] 217``` 218 219```ts 220import { cardEmulation } from '@kit.ConnectivityKit'; 221import { BusinessError } from '@kit.BasicServicesKit'; 222import { hilog } from '@kit.PerformanceAnalysisKit'; 223import { AsyncCallback } from '@kit.BasicServicesKit'; 224import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; 225 226let hceElementName : bundleManager.ElementName; 227let hceService: cardEmulation.HceService; 228 229const hceCommandCb : AsyncCallback<number[]> = (error : BusinessError, hceCommand : number[]) => { 230 if (!error) { 231 if (hceCommand == null || hceCommand == undefined) { 232 hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.'); 233 return; 234 } 235 236 // check the command, then transmit the response. 237 hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand)); 238 let responseData = [0x90, 0x00]; // change the response depend on different received command. 239 hceService.transmit(responseData).then(() => { 240 hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.'); 241 }).catch((err: BusinessError) => { 242 hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err)); 243 }); 244 } else { 245 hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error)); 246 } 247} 248 249export default class EntryAbility extends UIAbility { 250 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 251 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 252 253 // Check whether the device supports the NFC and HCE capabilities. 254 if (!canIUse("SystemCapability.Communication.NFC.Core")) { 255 hilog.error(0x0000, 'testTag', 'nfc unavailable.'); 256 return; 257 } 258 if (!cardEmulation.hasHceCapability()) { 259 hilog.error(0x0000, 'testTag', 'hce unavailable.'); 260 return; 261 } 262 263 hceElementName = { 264 bundleName: want.bundleName ?? '', 265 abilityName: want.abilityName ?? '', 266 moduleName: want.moduleName, 267 } 268 hceService = new cardEmulation.HceService(); 269 hceService.on('hceCmd', hceCommandCb); 270 } 271 272 onForeground() { 273 // Ability is brought to foreground. 274 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); 275 } 276 277 onDestroy() { 278 // Ability has back to destroy 279 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); 280 // When exiting the NFC tag page of the application, call the tag module API to exit the foreground mode. 281 if (hceElementName != undefined) { 282 try { 283 hceService.stop(hceElementName); 284 } catch (error) { 285 hilog.error(0x0000, 'testTag', 'hceService.stop error = %{public}s', JSON.stringify(error)); 286 } 287 } 288 } 289} 290``` 291