• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# HCE Development
2
3## Introduction
4Near Field Communication (NFC) is a short-range, high-frequency radio technology that operates at a frequency of 13.56 MHz, with a typical communication range of within 10 centimeters. 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 card swiping<br>
9In the foreground mode, the user has to start a specific application that 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. When the application switches to the background or exits, the foreground priority is also suspended.
10- HCE background card swiping<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 Applet 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. In this case, the user needs to open the desired HCE application and tap the device on the NFC card reader again to trigger the card swiping transaction.
12
13## Constraints
141. For security reasons, regardless of whether the HCE application performs card swiping in the foreground or background, the device does not support HCE card swiping operations when it is in the screen-off state.<br>
152. A device must be equipped with an NFC controller chip to support HCE card swiping capabilities. There are no constraints on whether it has an NFC secure element.<br>
163. An HCE application must declare the NFC card emulation permission. For specific details, see the sample code.<br>
17
18## Available APIs
19
20For details about the APIs and sample code, [NFC Card Emulation](../../reference/apis-connectivity-kit/js-apis-cardEmulation.md).
21
22The following table describes the APIs for implementing HCE.
23
24| API                            | Description                                                                      |
25| ---------------------------------- | ------------------------------------------------------------------------------ |
26| start(elementName: ElementName, aidList: string[]): void                   | Starts HCE, including enabling this application to run in the foreground preferentially and dynamically registering the AID list.                                                              |
27| 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.                                                    |
28| on(type: 'hceCmd', callback: AsyncCallback\<number[]>): void                | Registers a callback to receive APDUs from the peer card reader.                                                    |
29| transmit(response: number[]): Promise\<void>                  | Transmits APDU data to the peer card reader.|
30| off(type: 'hceCmd', callback?: AsyncCallback\<number[]>): void| Unsubscribes from events indicating receiving of APDUs from the peer card reader.|
31
32## Preparations
33
34### Selecting Foreground or Background Card Swiping
35HCE application developers can choose to implement either foreground or background card swiping based on service requirements. These two methods differ in their code implementation.
36- HCE Foreground Card Swiping<br>
371. In the **module.json5** configuration file, there is no need to statically declare the AID selected by the NFC card reader. Instead, dynamically register an AID by using [start](../../reference/apis-connectivity-kit/js-apis-cardEmulation.md#start9).
382. When the card swiping page of the HCE application exits,  explicitly called [stop](../../reference/apis-connectivity-kit/js-apis-cardEmulation.md#stop9) to release the dynamically registered AID.
39- HCE Background Card Swiping<br>
401. In the **module.json5** configuration file, statically declare the AID selected by the NFC card reader. Based on service requirements, specify whether the declared AID belongs to the **Payment** type or the **Other** type.
412. If the **Payment** type is selected, the HCE application will appear in the default payment app list on the NFC settings page. Users can only use background card swiping after selecting this HCE application as the default payment app. Since a default payment app is designated, there will be no conflicts between multiple HCE applications of the **Payment** type.
423. If the **Other** type is selected, the HCE application will not appear in the default payment app list on the NFC settings page. However, conflicts may arise if multiple HCE applications declare the same AID of the **Other** type.
434. When implementing HCE background card swiping, you do not need to call the **start** and **stop** APIs.
44
45> **NOTE**
46>
47> - Starting from API version 9, application development supports the Stage model, which is recommended for long-term evolution.
48> - All the HCE sample code in this document is based on the Stage model.
49
50## How to Develop
51
52### HCE Foreground Card Swiping
531. Declare the permission required for NFC card emulation and HCE action in the **module.json5** file.
542. Import modules.
553. Check whether the device supports the NFC and HCE capabilities.
564. Enable the foreground HCE application to preferentially process NFC card swiping.
575. Subscribe to the HCE APDU receiving events.
586. Receive and send APDU data for HCE card swiping.
597. Exit the HCE foreground mode when the application exits the NFC card swiping page.
60
61```ts
62    "abilities": [
63      {
64        "name": "EntryAbility",
65        "srcEntry": "./ets/entryability/EntryAbility.ts",
66        "description": "$string:EntryAbility_desc",
67        "icon": "$media:icon",
68        "label": "$string:EntryAbility_label",
69        "startWindowIcon": "$media:icon",
70        "startWindowBackground": "$color:start_window_background",
71        "exported": true,
72        "skills": [
73          {
74            "entities": [
75              "entity.system.home"
76            ],
77            "actions": [
78              "ohos.want.action.home",
79
80              // The **actions** field must contain ohos.nfc.cardemulation.action.HOST_APDU_SERVICE.
81              "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE"
82            ]
83          }
84        ]
85      }
86    ],
87    "requestPermissions": [
88      {
89        // Add the permission required for NFC card emulation.
90        "name": "ohos.permission.NFC_CARD_EMULATION",
91        "reason": "$string:app_name",
92      }
93    ]
94```
95
96```ts
97import { cardEmulation } from '@kit.ConnectivityKit';
98import { BusinessError } from '@kit.BasicServicesKit';
99import { hilog } from '@kit.PerformanceAnalysisKit';
100import { AsyncCallback } from '@kit.BasicServicesKit';
101import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit';
102
103let hceElementName: bundleManager.ElementName;
104let hceService: cardEmulation.HceService;
105
106const hceCommandCb : AsyncCallback<number[]> = (error : BusinessError, hceCommand : number[]) => {
107  if (!error) {
108    if (hceCommand == null || hceCommand == undefined) {
109      hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.');
110      return;
111    }
112    // The application checks the content of the received command and sends the matching response data based on its own service implementation.
113    hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand));
114    let responseData = [0x90, 0x00]; // Change the response data based on the received command.
115    hceService.transmit(responseData).then(() => {
116      hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.');
117    }).catch((err: BusinessError) => {
118      hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err));
119    });
120  } else {
121    hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error));
122  }
123}
124
125export default class EntryAbility extends UIAbility {
126  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
127    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
128
129    // Check whether the device supports the NFC and HCE capabilities.
130    if (!canIUse("SystemCapability.Communication.NFC.Core")) {
131      hilog.error(0x0000, 'testTag', 'nfc unavailable.');
132      return;
133    }
134    if (!cardEmulation.hasHceCapability()) {
135      hilog.error(0x0000, 'testTag', 'hce unavailable.');
136      return;
137    }
138
139    // Initialize the correct value based on the application information.
140    hceElementName = {
141      bundleName: want.bundleName ?? '',
142      abilityName: want.abilityName ?? '',
143      moduleName: want.moduleName,
144    }
145    hceService = new cardEmulation.HceService();
146  }
147
148  onForeground() {
149    // Switch the application to the foreground.
150    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
151    if (hceElementName != undefined) {
152      try {
153        // Enable the foreground HCE application to preferentially process NFC card swiping.
154        let aidList = ["A0000000031010," "A0000000031011"]; // Set the AID list correctly.
155        hceService.start(hceElementName, aidList);
156
157        // Subscribe to the HCE APDU receiving events.
158        hceService.on('hceCmd', hceCommandCb);
159      } catch (error) {
160        hilog.error(0x0000, 'testTag', 'hceService.start error = %{public}s', JSON.stringify(error));
161      }
162    }
163  }
164
165  onBackground() {
166    // Switch the application to the background.
167    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
168    // When exiting the NFC tag page of the application, call the tag module API to exit the foreground mode.
169    if (hceElementName != undefined) {
170      try {
171        hceService.stop(hceElementName);
172      } catch (error) {
173        hilog.error(0x0000, 'testTag', 'hceService.stop error = %{public}s', JSON.stringify(error));
174      }
175    }
176  }
177}
178```
179
180### HCE Background Card Swiping
1811. Declare the permission required for NFC card emulation, HCE action, and AIDs for application matching in the **module.json5** file.
1822. Import modules.
1833. Check whether the device supports the NFC and HCE capabilities.
1844. Subscribe to the HCE APDU receiving events.
1855. Receive and send APDU data for HCE card swiping.
1866. Cancel the subscription when the application exits.
187
188```ts
189    "abilities": [
190      {
191        "name": "EntryAbility",
192        "srcEntry": "./ets/entryability/EntryAbility.ts",
193        "description": "$string:EntryAbility_desc",
194        "icon": "$media:icon",
195        "label": "$string:EntryAbility_label",
196        "startWindowIcon": "$media:icon",
197        "startWindowBackground": "$color:start_window_background",
198        "exported": true,
199        "skills": [
200          {
201            "entities": [
202              "entity.system.home"
203            ],
204            "actions": [
205              "ohos.want.action.home",
206
207              // The **actions** field must contain ohos.nfc.cardemulation.action.HOST_APDU_SERVICE.
208              "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE"
209            ]
210          }
211        ],
212
213        // Define at least one AID of the Payment or Other type based on service requirements.
214        "metadata": [
215          {
216            "name": "payment-aid",
217            "value": "A0000000031010" // Define the AID of the Payment type.
218          },
219          {
220            "name": "other-aid",
221            "value": "A0000000031011" // Define the AID of the Other type.
222          }
223        ]
224      }
225    ],
226    "requestPermissions": [
227      {
228        // Add the permission required for NFC card emulation.
229        "name": "ohos.permission.NFC_CARD_EMULATION",
230        "reason": "$string:app_name",
231      }
232    ]
233```
234
235```ts
236import { cardEmulation } from '@kit.ConnectivityKit';
237import { BusinessError } from '@kit.BasicServicesKit';
238import { hilog } from '@kit.PerformanceAnalysisKit';
239import { AsyncCallback } from '@kit.BasicServicesKit';
240import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit';
241
242let hceElementName : bundleManager.ElementName;
243let hceService: cardEmulation.HceService;
244
245const hceCommandCb : AsyncCallback<number[]> = (error : BusinessError, hceCommand : number[]) => {
246  if (!error) {
247    if (hceCommand == null || hceCommand == undefined) {
248      hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.');
249      return;
250    }
251
252    // The application checks the content of the received command and sends the matching response based on its own service implementation.
253    hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand));
254    let responseData = [0x90, 0x00]; // Change the response data based on the received command.
255    hceService.transmit(responseData).then(() => {
256      hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.');
257    }).catch((err: BusinessError) => {
258      hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err));
259    });
260  } else {
261    hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error));
262  }
263}
264
265export default class EntryAbility extends UIAbility {
266  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
267    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
268
269    // Check whether the device supports the NFC and HCE capabilities.
270    if (!canIUse("SystemCapability.Communication.NFC.Core")) {
271      hilog.error(0x0000, 'testTag', 'nfc unavailable.');
272      return;
273    }
274    if (!cardEmulation.hasHceCapability()) {
275      hilog.error(0x0000, 'testTag', 'hce unavailable.');
276      return;
277    }
278
279    // Subscribe to HCE card swiping data when the application is running in the foreground.
280    hceService = new cardEmulation.HceService();
281    hceService.on('hceCmd', hceCommandCb);
282  }
283
284  onForeground() {
285    // Switch the application to the foreground.
286    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
287  }
288
289  onDestroy() {
290    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
291    // Unsubscribe from HCE card swiping data when the application exits.
292    hceService.off('hceCmd', hceCommandCb);
293  }
294}
295```
296