Adds Host card emulation (HCE) capabilities to React Native
Host Card Emulation is the technology in Android Devices, that let the device act as a host in the NFC communication. This technology can be used, e.g. to simulate the passive smart cards or NFC tags.
This package allows the react-native
application to use the adventages of this technology.
For now, the only out-of-the-box solution provided by this package is:
anyways, the module's architecture is ready to engage also the new, other usages.
Core part of the library (on the native side) is a Service which implements HostApduService
Android interface.
The key difference between usual Android services and HostApduService
is the initializer entity.
HostApduService
is initiated by OS - when phone taps the NFC reader. Thus, the Service (and - in the big
picture - the entire library) has been prepared to the case, when the React
Activity is in the background or even not available at the time in time of card data transfer.
Because of this special behavior of HostApduService
, we have chosen
the "declarativeness over interactivity" approach in the architecture design.
To make the transactions stable and reliable, library stores the state
on the Native side (in Android, the data are stored in SharedPreferences
). The application can specify
the available data in advance, to store it to native memory right away and
pass it efficiently to the Service, if needed. Also, the Service can pass the data to a storage
without considering the presence of JS thread. React app can grab the saved data later on.
Of course, all of this synchronization operations are handled in the React part of the library,
so the end user can control the entire HCE session with convenient abstraction - the HCEService
class.
The library also provides the convenient wrapper that binds the HCEService with React application lifecycle using the
"Contexts" feature of React.js.
npm install react-native-hce --save
or
yarn add react-native-hce
...up to Your preferences and project configuration. Autolinking will take care about the rest.
After the installation, following changes must be made inside the <projectRoot>/android
:
Create new file aid_list.xml
in <projectRoot>/android/app/src/main/res/xml
directory. Create the directory, if it does not exist yet.
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/app_name"
android:requireDeviceUnlock="false">
<aid-group android:category="other"
android:description="@string/app_name">
<!-- Create a separate <aid-filer /> node for each NFC application ID, that You intent to emulate/host. -->
<!-- For the NFC Type 4 tag emulation, let's put "D2760000850101" -->
<aid-filter android:name="D2760000850101" />
</aid-group>
</host-apdu-service>
Open the app's manifest (<projectRoot>/android/app/src/main/AndroidManifest.xml
):
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.reactnativehce">
<uses-permission android:name="android.permission.INTERNET" />
<!-- add the following two nodes: -->
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
...
</manifest>
react-native-hce
module communicating with this service, so that's why we need to place the reference in AndroidManifest.<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<!-- ... -->
<!-- Add the following block: -->
<service
android:name="com.reactnativehce.services.CardService"
android:exported="true"
android:enabled="false"
android:permission="android.permission.BIND_NFC_SERVICE" >
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data
android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/aid_list" />
</service>
<!-- ... -->
</application>
That's it.
You can find the generated documentation on the project's website.
You can try out the example react-native app, which presents the usage of this package in practice. The instructions regarding starting up the example application are provided in Contribution guide.
Inspired by underwindfall's NFC Type 4 tag communication handling used in NFCAndroid.
Note! If You want to use this feature, make sure that You added the proper aid to Your aid_list.xml
. Otherwise, the app will not handle any signal of NFC reader related with NFC Tags v4.
This is how to enable the NFC Tag emulation:
import { HCESession, NFCTagType4NDEFContentType, NFCTagType4 } from 'react-native-hce';
let session;
const startSession = async () => {
const tag = new NFCTagType4({
type: NFCTagType4NDEFContentType.Text,
content: "Hello world",
writable: false
});
session = await HCESession.getInstance();
session.setApplication(tag);
await session.setEnabled(true);
}
startSession();
stops this way:
const stopSession = async () => {
await session.setEnabled(false);
}
stopSimulation();
It is possible to listen for events during the emulation:
const listen = async () => {
const removeListener = session.on(HCESession.Events.HCE_STATE_READ, () => {
ToastAndroid.show("The tag has been read! Thank You.", ToastAndroid.LONG);
});
// to remove the listener:
removeListener();
}
listen();
Example application shows also the usage of writable tag feature.
This project is opened for Your ideas. You can contribute to the library and add the other functionalities, if You eager.
This project has been bootstrapped with Bob.
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT