• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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