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