I need to read NFC Tag ID in react native android app. I tried using nfc-react-native module but unfortunately it didn't work for me. So I've edited it.
I went through all documentations / articles about using NFC tag in react-native, writing custom android (native) components for react native but no success.
With help of some other questions here, I could manage to register the app to run when a NFC Tag have been tapped to the device. But I couldn't pass the Intent data to javascript. I read somewhere that I need to register the activity to receive the Intent. But I don't have any native activity.
I'd really appreciate your time and attention. I've been working so long on it without any success.
Here is the code : This is a custom module to read NFC tag ( edited nfc-react-module )
package es.tiarg.nfcreactnative;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableNativeArray;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import static com.facebook.common.util.Hex.hexStringToByteArray;
import android.app.Activity;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.support.annotation.Nullable;
import android.util.Log;
import android.content.Context;
import android.content.ServiceConnection;
import android.os.RemoteException;
import static android.R.attr.data;
import static android.R.attr.defaultValue;
import static android.R.attr.x;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
class NfcReactNativeModule extends ReactContextBaseJavaModule implements ActivityEventListener, LifecycleEventListener {
private ReactApplicationContext reactContext;
private NfcAdapter mNfcAdapter;
final protected static char[] HAX_ARRAY = "0123456789ABCDEF".toCharArray();
public static final String TAG = "NFCCardID";
public NfcReactNativeModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
this.reactContext.addActivityEventListener(this);
this.reactContext.addLifecycleEventListener(this);
}
@Override
public void onNewIntent(Intent intent) {
Log.i(TAG, "got new intent");
handleIntent(intent);
}
public void handleIntent(Intent intent) {
String action = intent.getAction();
Log.i(TAG, "New intent action:" + action);
if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] id = tag.getId();
String serialNumber = bytesToHex(id);
WritableMap idData = Arguments.createMap();
idData.putString("id", serialNumber);
sendEvent(this.reactContext, "NFCCardID", idData);
Log.i(TAG, "Serial number from nfc:" + serialNumber);
} else {
Log.i(TAG, "Error:" + action);
}
}
@Override
public void onHostResume() {
// Activity `onResume`
}
@Override
public void onHostPause() {
// Activity `onPause`
}
@Override
public void onHostDestroy() {
// Activity `onDestroy`
}
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
//int v = bytes[j] & 0xFF;
int v = bytes[bytes.length - j - 1] & 0xFF;
hexChars[j * 2] = HAX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HAX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
@Override
public void onActivityResult(
final Activity activity,
final int requestCode,
final int resultCode,
final Intent intent) {
//intent.getData();
Log.i(TAG, "Data received from Intent:" + intent.getData());
}
@Override
public String getName() {
return "NfcReactNative";
}
private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.****APPNAME*****.android.client"
android:versionCode="4"
android:versionName="2.1">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/****APPNAME*****"
android:theme="@style/SplashTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:label="filter_react_native">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="****APPNAME*****" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationRegistrationService"/>
<service
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
</application>
</manifest>
android/app/src/main/res/xml/nfc_tech_filter.xml
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcB</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcF</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcV</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NdefFormatable</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.MifareClassic</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcBarcode</tech>
</tech-list>
</resources>
Javascript/ react native side
import {
NativeModules,
DeviceEventEmitter
} from 'react-native';
DeviceEventEmitter.addListener('NFCCardID', function (data) {
console.log(data);
});
Thanks in advance.