@icedevml/react-native-host-card-emulation 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +17 -17
- package/RTNHCEModuleIOS.podspec +19 -19
- package/android/build.gradle +33 -33
- package/android/src/main/AndroidMainfest.xml +3 -3
- package/android/src/main/java/com/itsecrnd/rtnhceandroid/AESGCMUtil.java +89 -89
- package/android/src/main/java/com/itsecrnd/rtnhceandroid/BinaryUtils.java +65 -65
- package/android/src/main/java/com/itsecrnd/rtnhceandroid/HCEService.java +92 -92
- package/android/src/main/java/com/itsecrnd/rtnhceandroid/IntentKeys.java +6 -6
- package/android/src/main/java/com/itsecrnd/rtnhceandroid/RTNHCEAndroidModule.java +148 -148
- package/android/src/main/java/com/itsecrnd/rtnhceandroid/RTNHCEAndroidPackage.java +47 -47
- package/ios/RTNHCEModuleIOS-Bridging-Header.h +1 -1
- package/ios/RTNHCEModuleIOS.h +12 -12
- package/ios/RTNHCEModuleIOS.mm +125 -125
- package/ios/RTNHCEModuleIOSImpl.swift +190 -190
- package/js/NativeHCEModule.ts +33 -33
- package/package.json +1 -1
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
package com.itsecrnd.rtnhceandroid;
|
|
2
|
-
|
|
3
|
-
import static com.itsecrnd.rtnhceandroid.IntentKeys.INTENT_RECEIVE_C_APDU;
|
|
4
|
-
import static com.itsecrnd.rtnhceandroid.IntentKeys.INTENT_SEND_R_APDU;
|
|
5
|
-
|
|
6
|
-
import android.content.BroadcastReceiver;
|
|
7
|
-
import android.content.Context;
|
|
8
|
-
import android.content.Intent;
|
|
9
|
-
import android.content.IntentFilter;
|
|
10
|
-
import android.nfc.cardemulation.HostApduService;
|
|
11
|
-
import android.nfc.cardemulation.PollingFrame;
|
|
12
|
-
import android.os.Build;
|
|
13
|
-
import android.os.Bundle;
|
|
14
|
-
import android.util.Log;
|
|
15
|
-
|
|
16
|
-
import androidx.annotation.NonNull;
|
|
17
|
-
import androidx.annotation.RequiresApi;
|
|
18
|
-
|
|
19
|
-
import java.util.List;
|
|
20
|
-
import java.util.Locale;
|
|
21
|
-
|
|
22
|
-
import javax.crypto.SecretKey;
|
|
23
|
-
import javax.crypto.spec.SecretKeySpec;
|
|
24
|
-
|
|
25
|
-
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
26
|
-
public class HCEService extends HostApduService {
|
|
27
|
-
private static final String TAG = "HCEService";
|
|
28
|
-
|
|
29
|
-
private SecretKey encSecretKey;
|
|
30
|
-
|
|
31
|
-
private final BroadcastReceiver receiver = new BroadcastReceiver() {
|
|
32
|
-
@Override
|
|
33
|
-
public void onReceive(Context context, Intent intent) {
|
|
34
|
-
String action = intent.getAction();
|
|
35
|
-
|
|
36
|
-
if (action != null && action.equals(INTENT_SEND_R_APDU)) {
|
|
37
|
-
String rapdu = AESGCMUtil.decryptData(encSecretKey, intent.getStringExtra("rapdu"));
|
|
38
|
-
byte[] dec = BinaryUtils.HexStringToByteArray(rapdu.toUpperCase(Locale.ROOT));
|
|
39
|
-
sendResponseApdu(dec);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
@Override
|
|
45
|
-
public byte[] processCommandApdu(byte[] command, Bundle extras) {
|
|
46
|
-
String capdu = AESGCMUtil.encryptData(encSecretKey, BinaryUtils.ByteArrayToHexString(command));
|
|
47
|
-
|
|
48
|
-
Intent intent = new Intent(INTENT_RECEIVE_C_APDU);
|
|
49
|
-
intent.setPackage(getApplicationContext().getPackageName());
|
|
50
|
-
intent.putExtra("capdu", capdu);
|
|
51
|
-
getApplicationContext().sendBroadcast(intent);
|
|
52
|
-
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
@Override
|
|
57
|
-
public void processPollingFrames(@NonNull List<PollingFrame> frames) {
|
|
58
|
-
super.processPollingFrames(frames);
|
|
59
|
-
Log.i(TAG, "Polling frames: " + frames.size());
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
@Override
|
|
63
|
-
public void onCreate() {
|
|
64
|
-
Log.d(TAG, "Starting service");
|
|
65
|
-
|
|
66
|
-
IntentFilter filter = new IntentFilter();
|
|
67
|
-
filter.addAction(INTENT_SEND_R_APDU);
|
|
68
|
-
|
|
69
|
-
String encKey = getApplicationContext()
|
|
70
|
-
.getSharedPreferences("RTNHCEAndroidModuleBroadcastEnc", Context.MODE_PRIVATE)
|
|
71
|
-
.getString("encKey", "");
|
|
72
|
-
|
|
73
|
-
if (encKey.isEmpty()) {
|
|
74
|
-
throw new RuntimeException("Failed to load encKey.");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
byte[] bArr = BinaryUtils.HexStringToByteArray(encKey);
|
|
78
|
-
encSecretKey = new SecretKeySpec(bArr, 0, bArr.length, "AES");
|
|
79
|
-
|
|
80
|
-
/*
|
|
81
|
-
* See a comment about registerReceiver() in RTNHCEAndroidModule.
|
|
82
|
-
*/
|
|
83
|
-
getApplicationContext().registerReceiver(receiver, filter, RECEIVER_EXPORTED);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
@Override
|
|
87
|
-
public void onDeactivated(int reason) {
|
|
88
|
-
Log.d(TAG, "Finishing service: " + reason);
|
|
89
|
-
|
|
90
|
-
getApplicationContext().unregisterReceiver(receiver);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
1
|
+
package com.itsecrnd.rtnhceandroid;
|
|
2
|
+
|
|
3
|
+
import static com.itsecrnd.rtnhceandroid.IntentKeys.INTENT_RECEIVE_C_APDU;
|
|
4
|
+
import static com.itsecrnd.rtnhceandroid.IntentKeys.INTENT_SEND_R_APDU;
|
|
5
|
+
|
|
6
|
+
import android.content.BroadcastReceiver;
|
|
7
|
+
import android.content.Context;
|
|
8
|
+
import android.content.Intent;
|
|
9
|
+
import android.content.IntentFilter;
|
|
10
|
+
import android.nfc.cardemulation.HostApduService;
|
|
11
|
+
import android.nfc.cardemulation.PollingFrame;
|
|
12
|
+
import android.os.Build;
|
|
13
|
+
import android.os.Bundle;
|
|
14
|
+
import android.util.Log;
|
|
15
|
+
|
|
16
|
+
import androidx.annotation.NonNull;
|
|
17
|
+
import androidx.annotation.RequiresApi;
|
|
18
|
+
|
|
19
|
+
import java.util.List;
|
|
20
|
+
import java.util.Locale;
|
|
21
|
+
|
|
22
|
+
import javax.crypto.SecretKey;
|
|
23
|
+
import javax.crypto.spec.SecretKeySpec;
|
|
24
|
+
|
|
25
|
+
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
26
|
+
public class HCEService extends HostApduService {
|
|
27
|
+
private static final String TAG = "HCEService";
|
|
28
|
+
|
|
29
|
+
private SecretKey encSecretKey;
|
|
30
|
+
|
|
31
|
+
private final BroadcastReceiver receiver = new BroadcastReceiver() {
|
|
32
|
+
@Override
|
|
33
|
+
public void onReceive(Context context, Intent intent) {
|
|
34
|
+
String action = intent.getAction();
|
|
35
|
+
|
|
36
|
+
if (action != null && action.equals(INTENT_SEND_R_APDU)) {
|
|
37
|
+
String rapdu = AESGCMUtil.decryptData(encSecretKey, intent.getStringExtra("rapdu"));
|
|
38
|
+
byte[] dec = BinaryUtils.HexStringToByteArray(rapdu.toUpperCase(Locale.ROOT));
|
|
39
|
+
sendResponseApdu(dec);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public byte[] processCommandApdu(byte[] command, Bundle extras) {
|
|
46
|
+
String capdu = AESGCMUtil.encryptData(encSecretKey, BinaryUtils.ByteArrayToHexString(command));
|
|
47
|
+
|
|
48
|
+
Intent intent = new Intent(INTENT_RECEIVE_C_APDU);
|
|
49
|
+
intent.setPackage(getApplicationContext().getPackageName());
|
|
50
|
+
intent.putExtra("capdu", capdu);
|
|
51
|
+
getApplicationContext().sendBroadcast(intent);
|
|
52
|
+
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Override
|
|
57
|
+
public void processPollingFrames(@NonNull List<PollingFrame> frames) {
|
|
58
|
+
super.processPollingFrames(frames);
|
|
59
|
+
Log.i(TAG, "Polling frames: " + frames.size());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@Override
|
|
63
|
+
public void onCreate() {
|
|
64
|
+
Log.d(TAG, "Starting service");
|
|
65
|
+
|
|
66
|
+
IntentFilter filter = new IntentFilter();
|
|
67
|
+
filter.addAction(INTENT_SEND_R_APDU);
|
|
68
|
+
|
|
69
|
+
String encKey = getApplicationContext()
|
|
70
|
+
.getSharedPreferences("RTNHCEAndroidModuleBroadcastEnc", Context.MODE_PRIVATE)
|
|
71
|
+
.getString("encKey", "");
|
|
72
|
+
|
|
73
|
+
if (encKey.isEmpty()) {
|
|
74
|
+
throw new RuntimeException("Failed to load encKey.");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
byte[] bArr = BinaryUtils.HexStringToByteArray(encKey);
|
|
78
|
+
encSecretKey = new SecretKeySpec(bArr, 0, bArr.length, "AES");
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* See a comment about registerReceiver() in RTNHCEAndroidModule.
|
|
82
|
+
*/
|
|
83
|
+
getApplicationContext().registerReceiver(receiver, filter, RECEIVER_EXPORTED);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@Override
|
|
87
|
+
public void onDeactivated(int reason) {
|
|
88
|
+
Log.d(TAG, "Finishing service: " + reason);
|
|
89
|
+
|
|
90
|
+
getApplicationContext().unregisterReceiver(receiver);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
package com.itsecrnd.rtnhceandroid;
|
|
2
|
-
|
|
3
|
-
public class IntentKeys {
|
|
4
|
-
public static final String INTENT_RECEIVE_C_APDU = "com.itsecrnd.rtnhceandroid.receivecapdu";
|
|
5
|
-
public static final String INTENT_SEND_R_APDU = "com.itsecrnd.rtnhceandroid.sendrapdu";
|
|
6
|
-
}
|
|
1
|
+
package com.itsecrnd.rtnhceandroid;
|
|
2
|
+
|
|
3
|
+
public class IntentKeys {
|
|
4
|
+
public static final String INTENT_RECEIVE_C_APDU = "com.itsecrnd.rtnhceandroid.receivecapdu";
|
|
5
|
+
public static final String INTENT_SEND_R_APDU = "com.itsecrnd.rtnhceandroid.sendrapdu";
|
|
6
|
+
}
|
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
package com.itsecrnd.rtnhceandroid;
|
|
2
|
-
|
|
3
|
-
import static android.content.Context.RECEIVER_EXPORTED;
|
|
4
|
-
|
|
5
|
-
import static com.itsecrnd.rtnhceandroid.IntentKeys.INTENT_RECEIVE_C_APDU;
|
|
6
|
-
import static com.itsecrnd.rtnhceandroid.IntentKeys.INTENT_SEND_R_APDU;
|
|
7
|
-
|
|
8
|
-
import android.content.BroadcastReceiver;
|
|
9
|
-
import android.content.Context;
|
|
10
|
-
import android.content.Intent;
|
|
11
|
-
import android.content.IntentFilter;
|
|
12
|
-
import android.os.Build;
|
|
13
|
-
import android.util.Log;
|
|
14
|
-
|
|
15
|
-
import androidx.annotation.NonNull;
|
|
16
|
-
import androidx.annotation.RequiresApi;
|
|
17
|
-
|
|
18
|
-
import com.facebook.react.bridge.Arguments;
|
|
19
|
-
import com.facebook.react.bridge.Promise;
|
|
20
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
21
|
-
import com.facebook.react.bridge.WritableMap;
|
|
22
|
-
|
|
23
|
-
import javax.crypto.SecretKey;
|
|
24
|
-
|
|
25
|
-
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
26
|
-
public class RTNHCEAndroidModule extends NativeHCEModuleSpec {
|
|
27
|
-
public static final String TAG = "RTNHCEAndroidModule";
|
|
28
|
-
public static final String NAME = "NativeHCEModule";
|
|
29
|
-
|
|
30
|
-
private final SecretKey encSecretKey;
|
|
31
|
-
|
|
32
|
-
private final BroadcastReceiver receiver = new BroadcastReceiver() {
|
|
33
|
-
@Override
|
|
34
|
-
public void onReceive(Context context, Intent intent) {
|
|
35
|
-
String action = intent.getAction();
|
|
36
|
-
|
|
37
|
-
if (action != null && action.equals(INTENT_RECEIVE_C_APDU)) {
|
|
38
|
-
String capdu = AESGCMUtil.decryptData(encSecretKey, intent.getStringExtra("capdu"));
|
|
39
|
-
|
|
40
|
-
WritableMap map = Arguments.createMap();
|
|
41
|
-
map.putString("type", "received");
|
|
42
|
-
map.putString("arg", capdu);
|
|
43
|
-
emitOnEvent(map);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
RTNHCEAndroidModule(ReactApplicationContext context) {
|
|
49
|
-
super(context);
|
|
50
|
-
String encKey;
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
encSecretKey = AESGCMUtil.generateKey();
|
|
54
|
-
encKey = BinaryUtils.ByteArrayToHexString(encSecretKey.getEncoded());
|
|
55
|
-
} catch (Exception e) {
|
|
56
|
-
throw new RuntimeException("Failed to generate encryption key.", e);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
getReactApplicationContext()
|
|
60
|
-
.getSharedPreferences("RTNHCEAndroidModuleBroadcastEnc", Context.MODE_PRIVATE)
|
|
61
|
-
.edit()
|
|
62
|
-
.putString("encKey", encKey)
|
|
63
|
-
.commit();
|
|
64
|
-
|
|
65
|
-
IntentFilter filter = new IntentFilter();
|
|
66
|
-
filter.addAction(INTENT_RECEIVE_C_APDU);
|
|
67
|
-
|
|
68
|
-
/*
|
|
69
|
-
* FIXME It seems like those intents are not going through across this module and HostApduService.
|
|
70
|
-
* This happens even though those things are within the same application and package.
|
|
71
|
-
* It also seems like there is no way to bind HostApduService (or it's a skill issue).
|
|
72
|
-
*
|
|
73
|
-
* For now we will just encrypt&authenticate all messages using AES/GCM and use exported
|
|
74
|
-
* receivers. This is not a perfect solution but it is going to be secure and sufficient for now.
|
|
75
|
-
*
|
|
76
|
-
* If somebody knows a better way then any pull requests would be greatly appreciated.
|
|
77
|
-
*/
|
|
78
|
-
getReactApplicationContext().getApplicationContext().registerReceiver(receiver, filter, RECEIVER_EXPORTED);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
@Override
|
|
82
|
-
@NonNull
|
|
83
|
-
public String getName() {
|
|
84
|
-
return RTNHCEAndroidModule.NAME;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
@Override
|
|
88
|
-
public boolean isPlatformSupported() {
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
@Override
|
|
93
|
-
public void acquireExclusiveNFC(Promise promise) {
|
|
94
|
-
promise.resolve(null);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
@Override
|
|
98
|
-
public boolean isExclusiveNFC() {
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
@Override
|
|
103
|
-
public void beginSession(Promise promise) {
|
|
104
|
-
promise.resolve(null);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
@Override
|
|
108
|
-
public void setSessionAlertMessage(String message) {
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
@Override
|
|
113
|
-
public void invalidateSession() {
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
@Override
|
|
118
|
-
public boolean isSessionRunning() {
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
@Override
|
|
123
|
-
public void startHCE(Promise promise) {
|
|
124
|
-
promise.resolve(null);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
@Override
|
|
128
|
-
public void stopHCE(String status, Promise promise) {
|
|
129
|
-
promise.resolve(null);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
@Override
|
|
133
|
-
public void respondAPDU(String rapdu, Promise promise) {
|
|
134
|
-
String encRapdu = AESGCMUtil.encryptData(encSecretKey, rapdu);
|
|
135
|
-
|
|
136
|
-
Intent intent = new Intent(INTENT_SEND_R_APDU);
|
|
137
|
-
intent.setPackage(getReactApplicationContext().getPackageName());
|
|
138
|
-
intent.putExtra("rapdu", encRapdu);
|
|
139
|
-
getReactApplicationContext().getApplicationContext().sendBroadcast(intent);
|
|
140
|
-
|
|
141
|
-
promise.resolve(null);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
@Override
|
|
145
|
-
public void isHCERunning(Promise promise) {
|
|
146
|
-
promise.resolve(true);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
1
|
+
package com.itsecrnd.rtnhceandroid;
|
|
2
|
+
|
|
3
|
+
import static android.content.Context.RECEIVER_EXPORTED;
|
|
4
|
+
|
|
5
|
+
import static com.itsecrnd.rtnhceandroid.IntentKeys.INTENT_RECEIVE_C_APDU;
|
|
6
|
+
import static com.itsecrnd.rtnhceandroid.IntentKeys.INTENT_SEND_R_APDU;
|
|
7
|
+
|
|
8
|
+
import android.content.BroadcastReceiver;
|
|
9
|
+
import android.content.Context;
|
|
10
|
+
import android.content.Intent;
|
|
11
|
+
import android.content.IntentFilter;
|
|
12
|
+
import android.os.Build;
|
|
13
|
+
import android.util.Log;
|
|
14
|
+
|
|
15
|
+
import androidx.annotation.NonNull;
|
|
16
|
+
import androidx.annotation.RequiresApi;
|
|
17
|
+
|
|
18
|
+
import com.facebook.react.bridge.Arguments;
|
|
19
|
+
import com.facebook.react.bridge.Promise;
|
|
20
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
21
|
+
import com.facebook.react.bridge.WritableMap;
|
|
22
|
+
|
|
23
|
+
import javax.crypto.SecretKey;
|
|
24
|
+
|
|
25
|
+
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
26
|
+
public class RTNHCEAndroidModule extends NativeHCEModuleSpec {
|
|
27
|
+
public static final String TAG = "RTNHCEAndroidModule";
|
|
28
|
+
public static final String NAME = "NativeHCEModule";
|
|
29
|
+
|
|
30
|
+
private final SecretKey encSecretKey;
|
|
31
|
+
|
|
32
|
+
private final BroadcastReceiver receiver = new BroadcastReceiver() {
|
|
33
|
+
@Override
|
|
34
|
+
public void onReceive(Context context, Intent intent) {
|
|
35
|
+
String action = intent.getAction();
|
|
36
|
+
|
|
37
|
+
if (action != null && action.equals(INTENT_RECEIVE_C_APDU)) {
|
|
38
|
+
String capdu = AESGCMUtil.decryptData(encSecretKey, intent.getStringExtra("capdu"));
|
|
39
|
+
|
|
40
|
+
WritableMap map = Arguments.createMap();
|
|
41
|
+
map.putString("type", "received");
|
|
42
|
+
map.putString("arg", capdu);
|
|
43
|
+
emitOnEvent(map);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
RTNHCEAndroidModule(ReactApplicationContext context) {
|
|
49
|
+
super(context);
|
|
50
|
+
String encKey;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
encSecretKey = AESGCMUtil.generateKey();
|
|
54
|
+
encKey = BinaryUtils.ByteArrayToHexString(encSecretKey.getEncoded());
|
|
55
|
+
} catch (Exception e) {
|
|
56
|
+
throw new RuntimeException("Failed to generate encryption key.", e);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getReactApplicationContext()
|
|
60
|
+
.getSharedPreferences("RTNHCEAndroidModuleBroadcastEnc", Context.MODE_PRIVATE)
|
|
61
|
+
.edit()
|
|
62
|
+
.putString("encKey", encKey)
|
|
63
|
+
.commit();
|
|
64
|
+
|
|
65
|
+
IntentFilter filter = new IntentFilter();
|
|
66
|
+
filter.addAction(INTENT_RECEIVE_C_APDU);
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* FIXME It seems like those intents are not going through across this module and HostApduService.
|
|
70
|
+
* This happens even though those things are within the same application and package.
|
|
71
|
+
* It also seems like there is no way to bind HostApduService (or it's a skill issue).
|
|
72
|
+
*
|
|
73
|
+
* For now we will just encrypt&authenticate all messages using AES/GCM and use exported
|
|
74
|
+
* receivers. This is not a perfect solution but it is going to be secure and sufficient for now.
|
|
75
|
+
*
|
|
76
|
+
* If somebody knows a better way then any pull requests would be greatly appreciated.
|
|
77
|
+
*/
|
|
78
|
+
getReactApplicationContext().getApplicationContext().registerReceiver(receiver, filter, RECEIVER_EXPORTED);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@Override
|
|
82
|
+
@NonNull
|
|
83
|
+
public String getName() {
|
|
84
|
+
return RTNHCEAndroidModule.NAME;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Override
|
|
88
|
+
public boolean isPlatformSupported() {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@Override
|
|
93
|
+
public void acquireExclusiveNFC(Promise promise) {
|
|
94
|
+
promise.resolve(null);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@Override
|
|
98
|
+
public boolean isExclusiveNFC() {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@Override
|
|
103
|
+
public void beginSession(Promise promise) {
|
|
104
|
+
promise.resolve(null);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Override
|
|
108
|
+
public void setSessionAlertMessage(String message) {
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@Override
|
|
113
|
+
public void invalidateSession() {
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@Override
|
|
118
|
+
public boolean isSessionRunning() {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@Override
|
|
123
|
+
public void startHCE(Promise promise) {
|
|
124
|
+
promise.resolve(null);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@Override
|
|
128
|
+
public void stopHCE(String status, Promise promise) {
|
|
129
|
+
promise.resolve(null);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@Override
|
|
133
|
+
public void respondAPDU(String rapdu, Promise promise) {
|
|
134
|
+
String encRapdu = AESGCMUtil.encryptData(encSecretKey, rapdu);
|
|
135
|
+
|
|
136
|
+
Intent intent = new Intent(INTENT_SEND_R_APDU);
|
|
137
|
+
intent.setPackage(getReactApplicationContext().getPackageName());
|
|
138
|
+
intent.putExtra("rapdu", encRapdu);
|
|
139
|
+
getReactApplicationContext().getApplicationContext().sendBroadcast(intent);
|
|
140
|
+
|
|
141
|
+
promise.resolve(null);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@Override
|
|
145
|
+
public void isHCERunning(Promise promise) {
|
|
146
|
+
promise.resolve(true);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
package com.itsecrnd.rtnhceandroid;
|
|
2
|
-
|
|
3
|
-
import android.os.Build;
|
|
4
|
-
|
|
5
|
-
import androidx.annotation.Nullable;
|
|
6
|
-
import androidx.annotation.RequiresApi;
|
|
7
|
-
|
|
8
|
-
import com.facebook.react.TurboReactPackage;
|
|
9
|
-
import com.facebook.react.bridge.NativeModule;
|
|
10
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
11
|
-
import com.facebook.react.module.model.ReactModuleInfo;
|
|
12
|
-
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
13
|
-
|
|
14
|
-
import java.util.HashMap;
|
|
15
|
-
import java.util.Map;
|
|
16
|
-
|
|
17
|
-
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
18
|
-
public class RTNHCEAndroidPackage extends TurboReactPackage {
|
|
19
|
-
@Nullable
|
|
20
|
-
@Override
|
|
21
|
-
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
|
22
|
-
if (name.equals(RTNHCEAndroidModule.NAME)) {
|
|
23
|
-
return new RTNHCEAndroidModule(reactContext);
|
|
24
|
-
} else {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@Override
|
|
30
|
-
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
|
31
|
-
return () -> {
|
|
32
|
-
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
|
|
33
|
-
moduleInfos.put(
|
|
34
|
-
RTNHCEAndroidModule.NAME,
|
|
35
|
-
new ReactModuleInfo(
|
|
36
|
-
RTNHCEAndroidModule.NAME,
|
|
37
|
-
RTNHCEAndroidModule.NAME,
|
|
38
|
-
false, // canOverrideExistingModule
|
|
39
|
-
false, // needsEagerInit
|
|
40
|
-
true, // hasConstants
|
|
41
|
-
false, // isCxxModule
|
|
42
|
-
true // isTurboModule
|
|
43
|
-
));
|
|
44
|
-
return moduleInfos;
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
}
|
|
1
|
+
package com.itsecrnd.rtnhceandroid;
|
|
2
|
+
|
|
3
|
+
import android.os.Build;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.Nullable;
|
|
6
|
+
import androidx.annotation.RequiresApi;
|
|
7
|
+
|
|
8
|
+
import com.facebook.react.TurboReactPackage;
|
|
9
|
+
import com.facebook.react.bridge.NativeModule;
|
|
10
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
11
|
+
import com.facebook.react.module.model.ReactModuleInfo;
|
|
12
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
13
|
+
|
|
14
|
+
import java.util.HashMap;
|
|
15
|
+
import java.util.Map;
|
|
16
|
+
|
|
17
|
+
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
18
|
+
public class RTNHCEAndroidPackage extends TurboReactPackage {
|
|
19
|
+
@Nullable
|
|
20
|
+
@Override
|
|
21
|
+
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
|
22
|
+
if (name.equals(RTNHCEAndroidModule.NAME)) {
|
|
23
|
+
return new RTNHCEAndroidModule(reactContext);
|
|
24
|
+
} else {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Override
|
|
30
|
+
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
|
31
|
+
return () -> {
|
|
32
|
+
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
|
|
33
|
+
moduleInfos.put(
|
|
34
|
+
RTNHCEAndroidModule.NAME,
|
|
35
|
+
new ReactModuleInfo(
|
|
36
|
+
RTNHCEAndroidModule.NAME,
|
|
37
|
+
RTNHCEAndroidModule.NAME,
|
|
38
|
+
false, // canOverrideExistingModule
|
|
39
|
+
false, // needsEagerInit
|
|
40
|
+
true, // hasConstants
|
|
41
|
+
false, // isCxxModule
|
|
42
|
+
true // isTurboModule
|
|
43
|
+
));
|
|
44
|
+
return moduleInfos;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
#import <React-RCTAppDelegate/RCTDefaultReactNativeFactoryDelegate.h>
|
|
1
|
+
#import <React-RCTAppDelegate/RCTDefaultReactNativeFactoryDelegate.h>
|
package/ios/RTNHCEModuleIOS.h
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
-
#import <Foundation/Foundation.h>
|
|
3
|
-
#import <RTNHCEModuleSpec/RTNHCEModuleSpec.h>
|
|
4
|
-
|
|
5
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
-
|
|
7
|
-
@interface RTNHCEModuleIOS : NativeHCEModuleSpecBase <NativeHCEModuleSpec>
|
|
8
|
-
|
|
9
|
-
@end
|
|
10
|
-
|
|
11
|
-
NS_ASSUME_NONNULL_END
|
|
12
|
-
#endif
|
|
1
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
#import <Foundation/Foundation.h>
|
|
3
|
+
#import <RTNHCEModuleSpec/RTNHCEModuleSpec.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
@interface RTNHCEModuleIOS : NativeHCEModuleSpecBase <NativeHCEModuleSpec>
|
|
8
|
+
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_END
|
|
12
|
+
#endif
|