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<br> 9The 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. 10- HCE background mode<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 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. 12- Constraints<br> 131. 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.<br>2. The NFC card emulation permission must be declared in the **module.json5** file. For details, see the example below.<br>3. For foreground applications, the **start** and **stop** functions need to be called to register and deregister the AID. See the following development example for details.<br> 14 15## Available APIs 16 17For details about the JS APIs and sample code, [NFC Card Emulation](../../reference/apis-connectivity-kit/js-apis-cardEmulation.md). 18 19The following table describes the APIs for implementing HCE. 20 21| API | Description | 22| ---------------------------------- | ------------------------------------------------------------------------------ | 23| start(elementName: ElementName, aidList: string[]): void | Starts HCE, including enabling this application to run in the foreground preferentially and dynamically registering the AID list. | 24| 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. 25| on(type: 'hceCmd', callback: AsyncCallback\<number[]>): void | Registers a callback to receive APDUs from the peer card reader. 26| transmit(response: number[]): Promise\<void> | Transmits APDU data to the peer card reader.| | 27 28## How to Develop 29 30### HCE Foreground Mode 311. Declare the permission required for NFC card emulation and HCE action in the **module.json5** file. 322. Import modules. 333. Check whether the device supports the NFC and HCE capabilities. 344. Enable the foreground HCE application to preferentially process NFC card swiping. 355. Subscribe to the reception of HCE APDU data. 366. Receive and send APDU data for HCE card swiping. 377. Exit the HCE foreground mode when the application exits the NFC card swiping page. 38 39```ts 40 "abilities": [ 41 { 42 "name": "EntryAbility", 43 "srcEntry": "./ets/entryability/EntryAbility.ts", 44 "description": "$string:EntryAbility_desc", 45 "icon": "$media:icon", 46 "label": "$string:EntryAbility_label", 47 "startWindowIcon": "$media:icon", 48 "startWindowBackground": "$color:start_window_background", 49 "exported": true, 50 "skills": [ 51 { 52 "entities": [ 53 "entity.system.home" 54 ], 55 "actions": [ 56 "action.system.home", 57 58 // Make sure that ohos.nfc.cardemulation.action.HOST_APDU_SERVICE is present in actions. 59 "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE" 60 ] 61 } 62 ] 63 } 64 ], 65 "requestPermissions": [ 66 { 67 // Add the permission required for NFC card emulation. 68 "name": "ohos.permission.NFC_CARD_EMULATION", 69 "reason": "$string:app_name", 70 } 71 ] 72``` 73 74```ts 75import { cardEmulation } from '@kit.ConnectivityKit'; 76import { BusinessError } from '@kit.BasicServicesKit'; 77import { hilog } from '@kit.PerformanceAnalysisKit'; 78import { AsyncCallback } from '@kit.BasicServicesKit'; 79import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; 80 81let hceElementName: bundleManager.ElementName; 82let hceService: cardEmulation.HceService; 83 84const hceCommandCb : AsyncCallback<number[]> = (error : BusinessError, hceCommand : number[]) => { 85 if (!error) { 86 if (hceCommand == null || hceCommand == undefined) { 87 hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.'); 88 return; 89 } 90 // Check the command and send a response. 91 hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand)); 92 let responseData = [0x90, 0x00]; // Modify the response based on the received command. 93 hceService.transmit(responseData).then(() => { 94 hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.'); 95 }).catch((err: BusinessError) => { 96 hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err)); 97 }); 98 } else { 99 hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error)); 100 } 101} 102 103export default class EntryAbility extends UIAbility { 104 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 105 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 106 107 // Check whether the device supports the NFC and HCE capabilities. 108 if (!canIUse("SystemCapability.Communication.NFC.Core")) { 109 hilog.error(0x0000, 'testTag', 'nfc unavailable.'); 110 return; 111 } 112 if (!cardEmulation.hasHceCapability()) { 113 hilog.error(0x0000, 'testTag', 'hce unavailable.'); 114 return; 115 } 116 117 hceElementName = { 118 bundleName: want.bundleName ?? '', 119 abilityName: want.abilityName ?? '', 120 moduleName: want.moduleName, 121 } 122 hceService = new cardEmulation.HceService(); 123 } 124 125 onForeground() { 126 // Switch the application to the foreground. 127 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); 128 if (hceElementName != undefined) { 129 try { 130 // Enable the foreground HCE application to preferentially process NFC card swiping. 131 let aidList = ["A0000000031010," "A0000000031011"]; // Set the AID list correctly. 132 hceService.start(hceElementName, aidList); 133 134 // Subscribe to the reception of HCE APDU data. 135 hceService.on('hceCmd', hceCommandCb); 136 } catch (error) { 137 hilog.error(0x0000, 'testTag', 'hceService.start error = %{public}s', JSON.stringify(error)); 138 } 139 } 140 } 141 142 onBackground() { 143 // Switch the application to the background. 144 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); 145 // When exiting the NFC tag page of the application, call the tag module API to exit the foreground mode. 146 if (hceElementName != undefined) { 147 try { 148 hceService.stop(hceElementName); 149 } catch (error) { 150 hilog.error(0x0000, 'testTag', 'hceService.stop error = %{public}s', JSON.stringify(error)); 151 } 152 } 153 } 154} 155``` 156 157### HCE Background Mode 1581. Declare the permission required for NFC card emulation, HCE action, and AIDs for application matching in the **module.json5** file. 1592. Import modules. 1603. Check whether the device supports the NFC and HCE capabilities. 1614. Subscribe to the reception of HCE APDU data. 1625. Receive and send APDU data for HCE card swiping. 1636. Cancel the subscription when the application exits. 164 165```ts 166 "abilities": [ 167 { 168 "name": "EntryAbility", 169 "srcEntry": "./ets/entryability/EntryAbility.ts", 170 "description": "$string:EntryAbility_desc", 171 "icon": "$media:icon", 172 "label": "$string:EntryAbility_label", 173 "startWindowIcon": "$media:icon", 174 "startWindowBackground": "$color:start_window_background", 175 "exported": true, 176 "skills": [ 177 { 178 "entities": [ 179 "entity.system.home" 180 ], 181 "actions": [ 182 "action.system.home", 183 184 // Make sure that ohos.nfc.cardemulation.action.HOST_APDU_SERVICE is present in actions. 185 "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE" 186 ] 187 } 188 ], 189 "metadata": [ 190 { 191 "name": "payment-aid", 192 "value": "A0000000031010" // Set a correct AID. 193 }, 194 { 195 "name": "other-aid", 196 "value": "A0000000031011" // Set a correct AID. 197 } 198 ] 199 } 200 ], 201 "requestPermissions": [ 202 { 203 // Add the permission required for NFC card emulation. 204 "name": "ohos.permission.NFC_CARD_EMULATION", 205 "reason": "$string:app_name", 206 } 207 ] 208``` 209 210```ts 211import { cardEmulation } from '@kit.ConnectivityKit'; 212import { BusinessError } from '@kit.BasicServicesKit'; 213import { hilog } from '@kit.PerformanceAnalysisKit'; 214import { AsyncCallback } from '@kit.BasicServicesKit'; 215import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; 216 217let hceElementName : bundleManager.ElementName; 218let hceService: cardEmulation.HceService; 219 220const hceCommandCb : AsyncCallback<number[]> = (error : BusinessError, hceCommand : number[]) => { 221 if (!error) { 222 if (hceCommand == null || hceCommand == undefined) { 223 hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.'); 224 return; 225 } 226 227 // Check the command and send a response. 228 hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand)); 229 let responseData = [0x90, 0x00]; // change the response depend on different received command. 230 hceService.transmit(responseData).then(() => { 231 hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.'); 232 }).catch((err: BusinessError) => { 233 hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err)); 234 }); 235 } else { 236 hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error)); 237 } 238} 239 240export default class EntryAbility extends UIAbility { 241 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 242 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 243 244 // Check whether the device supports the NFC and HCE capabilities. 245 if (!canIUse("SystemCapability.Communication.NFC.Core")) { 246 hilog.error(0x0000, 'testTag', 'nfc unavailable.'); 247 return; 248 } 249 if (!cardEmulation.hasHceCapability()) { 250 hilog.error(0x0000, 'testTag', 'hce unavailable.'); 251 return; 252 } 253 254 hceElementName = { 255 bundleName: want.bundleName ?? '', 256 abilityName: want.abilityName ?? '', 257 moduleName: want.moduleName, 258 } 259 hceService = new cardEmulation.HceService(); 260 hceService.on('hceCmd', hceCommandCb); 261 } 262 263 onForeground() { 264 // Switch the application to the foreground. 265 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); 266 } 267 268 onDestroy() { 269 // Exit the application. 270 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); 271 // When exiting the NFC tag page of the application, call the tag module API to exit the foreground mode. 272 if (hceElementName != undefined) { 273 try { 274 hceService.stop(hceElementName); 275 } catch (error) { 276 hilog.error(0x0000, 'testTag', 'hceService.stop error = %{public}s', JSON.stringify(error)); 277 } 278 } 279 } 280} 281``` 282