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