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