react-native-shield-fraud-plugin 1.0.10 → 2.0.0
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/android/build.gradle +30 -12
- package/android/src/main/java/com/shieldfraudplugin/ShieldFraudPluginModule.java +354 -123
- package/android/src/main/java/com/shieldfraudplugin/ShieldFraudPluginPackage.java +71 -21
- package/android/src/newarch/java/com/shieldfraudplugin/ShieldFraudPluginSpec.java +41 -0
- package/android/src/oldarch/java/com/shieldfraudplugin/ShieldFraudPluginSpec.java +36 -0
- package/ios/ShieldFraudPlugin.h +11 -2
- package/ios/ShieldFraudPlugin.mm +289 -0
- package/lib/commonjs/NativeShieldFraudPlugin.js +15 -0
- package/lib/commonjs/NativeShieldFraudPlugin.js.map +1 -0
- package/lib/commonjs/index.js +80 -8
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/NativeShieldFraudPlugin.js +10 -0
- package/lib/module/NativeShieldFraudPlugin.js.map +1 -0
- package/lib/module/index.js +81 -9
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/NativeShieldFraudPlugin.d.ts +52 -0
- package/lib/typescript/NativeShieldFraudPlugin.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +41 -3
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +10 -2
- package/react-native-shield-fraud-plugin.podspec +13 -3
- package/src/NativeShieldFraudPlugin.ts +85 -0
- package/src/index.tsx +115 -11
- package/ios/ShieldFraudPlugin.m +0 -98
- package/ios/ShieldFraudPlugin.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/ios/ShieldFraudPlugin.xcodeproj/project.xcworkspace/xcuserdata/deepakraj.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/ShieldFraudPlugin.xcodeproj/xcuserdata/deepakraj.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
package/android/build.gradle
CHANGED
|
@@ -15,9 +15,6 @@ def isNewArchitectureEnabled() {
|
|
|
15
15
|
|
|
16
16
|
apply plugin: "com.android.library"
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }
|
|
20
|
-
|
|
21
18
|
if (isNewArchitectureEnabled()) {
|
|
22
19
|
apply plugin: "com.facebook.react"
|
|
23
20
|
}
|
|
@@ -33,11 +30,17 @@ def getExtOrIntegerDefault(name) {
|
|
|
33
30
|
android {
|
|
34
31
|
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
35
32
|
|
|
33
|
+
// Conditional for compatibility with AGP <4.2.
|
|
34
|
+
if (project.android.hasProperty("namespace")) {
|
|
35
|
+
namespace 'com.shieldfraudplugin'
|
|
36
|
+
}
|
|
37
|
+
|
|
36
38
|
defaultConfig {
|
|
37
39
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
38
40
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
39
41
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
40
42
|
}
|
|
43
|
+
|
|
41
44
|
buildTypes {
|
|
42
45
|
release {
|
|
43
46
|
minifyEnabled false
|
|
@@ -53,6 +56,18 @@ android {
|
|
|
53
56
|
targetCompatibility JavaVersion.VERSION_1_8
|
|
54
57
|
}
|
|
55
58
|
|
|
59
|
+
sourceSets {
|
|
60
|
+
main {
|
|
61
|
+
// Select the architecture-specific ShieldFraudPluginSpec shim at build time.
|
|
62
|
+
// - oldarch: extends ReactContextBaseJavaModule (Old Architecture / bridge)
|
|
63
|
+
// - newarch: extends the codegen-generated NativeShieldFraudPluginSpec (New Architecture)
|
|
64
|
+
if (isNewArchitectureEnabled()) {
|
|
65
|
+
java.srcDirs += ['src/newarch']
|
|
66
|
+
} else {
|
|
67
|
+
java.srcDirs += ['src/oldarch']
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
56
71
|
|
|
57
72
|
if (isNewArchitectureEnabled()) {
|
|
58
73
|
react {
|
|
@@ -65,21 +80,24 @@ android {
|
|
|
65
80
|
|
|
66
81
|
rootProject.allprojects {
|
|
67
82
|
repositories {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
83
|
+
mavenCentral()
|
|
84
|
+
google()
|
|
85
|
+
maven {
|
|
86
|
+
url "https://cashshield-sdk.s3.amazonaws.com/release/"
|
|
87
|
+
content {
|
|
88
|
+
includeGroup "com.shield.android"
|
|
89
|
+
includeGroup "com.shield.android.module"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
73
92
|
}
|
|
74
93
|
}
|
|
75
94
|
|
|
76
|
-
|
|
77
|
-
|
|
78
95
|
dependencies {
|
|
79
96
|
// For < 0.71, this will be from the local maven repo
|
|
80
97
|
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
81
98
|
//noinspection GradleDynamicVersion
|
|
82
99
|
implementation "com.facebook.react:react-native:+"
|
|
83
|
-
implementation 'com.shield.android:shield-fraud:1.6.+'
|
|
84
|
-
}
|
|
85
100
|
|
|
101
|
+
// Shield Fraud SDK 2.x — factory-based init, callback-based device intelligence
|
|
102
|
+
implementation 'com.shield.android:shield-fraud:2.4.0'
|
|
103
|
+
}
|
|
@@ -1,40 +1,79 @@
|
|
|
1
1
|
package com.shieldfraudplugin;
|
|
2
2
|
|
|
3
|
-
import android.app.
|
|
4
|
-
import android.os.Handler;
|
|
5
|
-
import android.os.Looper;
|
|
3
|
+
import android.app.Application;
|
|
6
4
|
|
|
7
5
|
import androidx.annotation.NonNull;
|
|
6
|
+
import androidx.annotation.Nullable;
|
|
8
7
|
|
|
9
8
|
import com.facebook.react.bridge.Arguments;
|
|
9
|
+
import com.facebook.react.bridge.Callback;
|
|
10
10
|
import com.facebook.react.bridge.Promise;
|
|
11
11
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
12
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
13
12
|
import com.facebook.react.bridge.ReactMethod;
|
|
13
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
14
|
+
import com.facebook.react.bridge.WritableArray;
|
|
14
15
|
import com.facebook.react.bridge.WritableMap;
|
|
15
16
|
import com.facebook.react.module.annotations.ReactModule;
|
|
16
|
-
|
|
17
|
-
import com.facebook.react.bridge.Callback;
|
|
18
|
-
import com.facebook.react.bridge.ReadableMap;
|
|
19
17
|
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
18
|
+
|
|
20
19
|
import com.shield.android.BlockedDialog;
|
|
20
|
+
import com.shield.android.DeviceIntelligence;
|
|
21
|
+
import com.shield.android.Environment;
|
|
22
|
+
import com.shield.android.LogLevel;
|
|
23
|
+
import com.shield.android.Result;
|
|
21
24
|
import com.shield.android.Shield;
|
|
22
|
-
import com.shield.android.
|
|
23
|
-
import com.shield.android.
|
|
25
|
+
import com.shield.android.ShieldConfig;
|
|
26
|
+
import com.shield.android.ShieldCrossPlatformHelper;
|
|
27
|
+
import com.shield.android.ShieldCrossPlatformParams;
|
|
28
|
+
import com.shield.android.ShieldError;
|
|
29
|
+
import com.shield.android.ShieldFactory;
|
|
24
30
|
|
|
31
|
+
import org.json.JSONArray;
|
|
25
32
|
import org.json.JSONObject;
|
|
26
33
|
|
|
27
34
|
import java.util.HashMap;
|
|
35
|
+
import java.util.Iterator;
|
|
28
36
|
import java.util.Map;
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
/**
|
|
39
|
+
* ShieldFraudPlugin native module — Shield SDK 2.x (pure Java)
|
|
40
|
+
*
|
|
41
|
+
* SDK 2.x migration summary
|
|
42
|
+
* ─────────────────────────
|
|
43
|
+
* 1. Initialisation : Shield.Builder → ShieldConfig + ShieldFactory
|
|
44
|
+
* 2. Instance access : Shield.getInstance() → stored `shield` member
|
|
45
|
+
* 3. Session ID : Shield.getInstance().getSessionId() → shield.getSessionId()
|
|
46
|
+
* 4. Device results : setDeviceResultStateListener(callback)
|
|
47
|
+
* → ShieldFactory.createShieldWithCallback (SHIELD Sentinel)
|
|
48
|
+
* 5. sendAttributes : void return
|
|
49
|
+
* → shield.sendAttributesWithCallback (Result<String> callback)
|
|
50
|
+
* 6. LogLevel enum : Shield.LogLevel.VERBOSE/DEBUG/INFO/NONE
|
|
51
|
+
* → LogLevel.DEBUG / INFO / NONE (VERBOSE removed)
|
|
52
|
+
* 7. Environment enum : String constants ENVIRONMENT_PROD / DEV / STAGING
|
|
53
|
+
* → Environment.PROD / DEV (STAGING removed)
|
|
54
|
+
*
|
|
55
|
+
* Architecture segmentation
|
|
56
|
+
* ─────────────────────────
|
|
57
|
+
* Handled by Gradle source sets (not #ifdef).
|
|
58
|
+
* src/oldarch/ShieldFraudPluginSpec.java → extends ReactContextBaseJavaModule
|
|
59
|
+
* src/newarch/ShieldFraudPluginSpec.java → extends NativeShieldFraudPluginSpec (codegen)
|
|
60
|
+
* This module always extends ShieldFraudPluginSpec.
|
|
61
|
+
*/
|
|
33
62
|
@ReactModule(name = ShieldFraudPluginModule.NAME)
|
|
34
|
-
public class ShieldFraudPluginModule extends
|
|
63
|
+
public class ShieldFraudPluginModule extends com.shieldfraudplugin.ShieldFraudPluginSpec {
|
|
64
|
+
|
|
35
65
|
public static final String NAME = "ShieldFraudPlugin";
|
|
66
|
+
|
|
36
67
|
private final ReactApplicationContext reactContext;
|
|
37
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Stored Shield instance — created once by ShieldFactory in initShield().
|
|
71
|
+
* All subsequent calls use this reference instead of a singleton accessor.
|
|
72
|
+
*/
|
|
73
|
+
@Nullable
|
|
74
|
+
private Shield shield = null;
|
|
75
|
+
|
|
76
|
+
|
|
38
77
|
public ShieldFraudPluginModule(ReactApplicationContext reactContext) {
|
|
39
78
|
super(reactContext);
|
|
40
79
|
this.reactContext = reactContext;
|
|
@@ -46,158 +85,350 @@ public class ShieldFraudPluginModule extends ReactContextBaseJavaModule implemen
|
|
|
46
85
|
return NAME;
|
|
47
86
|
}
|
|
48
87
|
|
|
88
|
+
// =========================================================================
|
|
89
|
+
// Synchronous state queries
|
|
90
|
+
// =========================================================================
|
|
91
|
+
|
|
49
92
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
50
93
|
public boolean isShieldInitialized() {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
94
|
+
return shield != null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
98
|
+
public String getSessionId() {
|
|
99
|
+
return shield != null ? shield.getSessionId() : "";
|
|
56
100
|
}
|
|
57
101
|
|
|
102
|
+
// =========================================================================
|
|
103
|
+
// SDK initialisation (Shield SDK 2.x — ShieldConfig + ShieldFactory)
|
|
104
|
+
//
|
|
105
|
+
// createShieldWithCallback both initialises the SDK and acts as the
|
|
106
|
+
// SHIELD Sentinel callback — it fires on the initial fingerprint and on
|
|
107
|
+
// every subsequent device intelligence update during the session.
|
|
108
|
+
//
|
|
109
|
+
// logLevel / environmentInfo arrive as `double` from both architectures:
|
|
110
|
+
// • Old Arch — JS bridge maps JS numbers to double.
|
|
111
|
+
// • New Arch — codegen generates double for TypeScript number params.
|
|
112
|
+
// =========================================================================
|
|
113
|
+
|
|
58
114
|
@ReactMethod
|
|
59
|
-
public void initShield(
|
|
115
|
+
public void initShield(
|
|
116
|
+
String siteID,
|
|
117
|
+
String secretKey,
|
|
118
|
+
boolean isOptimizedListener,
|
|
119
|
+
@Nullable ReadableMap blockedDialog,
|
|
120
|
+
double logLevel,
|
|
121
|
+
double environmentInfo,
|
|
122
|
+
boolean blockScreenRecording,
|
|
123
|
+
Promise promise) {
|
|
124
|
+
|
|
60
125
|
if (isShieldInitialized()) {
|
|
126
|
+
promise.resolve(null);
|
|
61
127
|
return;
|
|
62
128
|
}
|
|
63
|
-
Activity currentActivity = getCurrentActivity();
|
|
64
|
-
if (currentActivity != null) {
|
|
65
|
-
Shield.Builder builder = new Shield.Builder(currentActivity, siteID, secretKey)
|
|
66
|
-
.setAutoBlockDialog(getBlockedDialogFromReadableMap(blockedDialog));
|
|
67
129
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
130
|
+
Application application = (Application) reactContext.getApplicationContext();
|
|
131
|
+
|
|
132
|
+
ShieldConfig config = new ShieldConfig(siteID, secretKey);
|
|
133
|
+
config.setLogLevel(getLogLevelFromInt((int) logLevel));
|
|
134
|
+
config.setEnvironment(getEnvironmentFromInt((int) environmentInfo));
|
|
71
135
|
|
|
72
|
-
|
|
73
|
-
|
|
136
|
+
if (blockedDialog != null) {
|
|
137
|
+
String title = blockedDialog.hasKey("title") ? blockedDialog.getString("title") : null;
|
|
138
|
+
String body = blockedDialog.hasKey("body") ? blockedDialog.getString("body") : null;
|
|
139
|
+
config.setBlockedDialog(new BlockedDialog(title, body));
|
|
140
|
+
}
|
|
74
141
|
|
|
75
|
-
|
|
76
|
-
|
|
142
|
+
// blockScreenRecording is Android-only. JS always sends a real boolean
|
|
143
|
+
// (true/false, never null) so the Old Arch bridge can safely read it as
|
|
144
|
+
// a primitive. Defaults to false when the user doesn't set it in Config.
|
|
145
|
+
config.setBlockScreenRecording(blockScreenRecording);
|
|
77
146
|
|
|
78
|
-
|
|
79
|
-
|
|
147
|
+
if (isOptimizedListener) {
|
|
148
|
+
// SDK 2.x: createShieldWithCallback initialises + acts as the Sentinel.
|
|
149
|
+
// Unlike 1.x (which required a separate setDeviceResultStateListener() call
|
|
150
|
+
// on the SDK), 2.x fires this callback automatically when device intelligence
|
|
151
|
+
// is ready and on every subsequent risk-profile change.
|
|
152
|
+
// The callback may arrive on a background thread — always post to main looper.
|
|
153
|
+
shield = ShieldFactory.createShieldWithCallback(
|
|
154
|
+
application,
|
|
155
|
+
config,
|
|
156
|
+
result -> new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> {
|
|
157
|
+
if (result instanceof Result.Success) {
|
|
158
|
+
DeviceIntelligence di =
|
|
159
|
+
((Result.Success<DeviceIntelligence>) result).getData();
|
|
160
|
+
JSONObject json = di != null ? di.getData() : null;
|
|
161
|
+
emitEvent("success", json != null ? json.toString() : null);
|
|
162
|
+
} else if (result instanceof Result.Failure) {
|
|
163
|
+
ShieldError error =
|
|
164
|
+
((Result.Failure<DeviceIntelligence>) result).getError();
|
|
165
|
+
emitEvent("error", error.getErrorMessage());
|
|
166
|
+
}
|
|
167
|
+
}));
|
|
168
|
+
} else {
|
|
169
|
+
// createShield = initialise without the real-time Sentinel callback.
|
|
170
|
+
// Use getLatestDeviceResult() to poll on demand instead.
|
|
171
|
+
shield = ShieldFactory.createShield(application, config);
|
|
80
172
|
}
|
|
173
|
+
|
|
174
|
+
promise.resolve(null);
|
|
81
175
|
}
|
|
82
176
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
177
|
+
// =========================================================================
|
|
178
|
+
// Cross-platform metadata
|
|
179
|
+
// =========================================================================
|
|
180
|
+
|
|
181
|
+
@ReactMethod
|
|
182
|
+
public void setCrossPlatformParameters(String crossPlatformName, String crossPlatformVersion) {
|
|
183
|
+
ShieldCrossPlatformParams params =
|
|
184
|
+
new ShieldCrossPlatformParams(crossPlatformName, crossPlatformVersion);
|
|
185
|
+
ShieldCrossPlatformHelper.setCrossPlatformParameters(params);
|
|
90
186
|
}
|
|
91
187
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
188
|
+
// =========================================================================
|
|
189
|
+
// setDeviceResultStateListener — no-op stub (SDK 2.x)
|
|
190
|
+
//
|
|
191
|
+
// SDK 1.x required a manual subscription call + Handler.postDelayed workaround.
|
|
192
|
+
// SDK 2.x fires device result events automatically via createShieldWithCallback
|
|
193
|
+
// when isOptimizedListener == true — no subscription call needed.
|
|
194
|
+
//
|
|
195
|
+
// The method is kept as a no-op stub so the shared TypeScript codegen spec
|
|
196
|
+
// and iOS (which still calls the SDK method) remain unaffected.
|
|
197
|
+
// =========================================================================
|
|
198
|
+
|
|
199
|
+
@ReactMethod
|
|
200
|
+
public void setDeviceResultStateListener() {
|
|
201
|
+
// No-op on Android SDK 2.x — device result events are delivered
|
|
202
|
+
// automatically through the createShieldWithCallback Sentinel.
|
|
106
203
|
}
|
|
107
204
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
205
|
+
// =========================================================================
|
|
206
|
+
// Retrieve the latest device intelligence result
|
|
207
|
+
//
|
|
208
|
+
// Returns Shield SDK's latest device result payload.
|
|
209
|
+
// =========================================================================
|
|
210
|
+
|
|
211
|
+
@ReactMethod
|
|
212
|
+
public void getLatestDeviceResult(Callback successCallback, Callback errorCallback) {
|
|
213
|
+
if (shield == null) {
|
|
214
|
+
errorCallback.invoke("Shield SDK is not initialized.");
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
JSONObject json = shield.getLatestDeviceResult();
|
|
219
|
+
if (json == null) {
|
|
220
|
+
errorCallback.invoke("No device result available yet.");
|
|
221
|
+
return;
|
|
123
222
|
}
|
|
124
|
-
|
|
223
|
+
|
|
224
|
+
successCallback.invoke(toWritableMap(json));
|
|
125
225
|
}
|
|
126
226
|
|
|
227
|
+
// =========================================================================
|
|
228
|
+
// Send user / screen attributes (Shield SDK 2.x — sendAttributesWithCallback)
|
|
229
|
+
//
|
|
230
|
+
// sendAttributesWithCallback delivers a Result<String> where the String
|
|
231
|
+
// is the sessionId on success.
|
|
232
|
+
// =========================================================================
|
|
233
|
+
|
|
127
234
|
@ReactMethod
|
|
128
|
-
public void
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
params.putString("status", "isSDKReady");
|
|
138
|
-
reactContext
|
|
139
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
140
|
-
.emit("device_result_state", params);
|
|
141
|
-
}
|
|
142
|
-
});
|
|
235
|
+
public void sendAttributes(String screenName, ReadableMap json) {
|
|
236
|
+
if (shield == null) return;
|
|
237
|
+
|
|
238
|
+
Map<String, String> data = toStringMap(json);
|
|
239
|
+
|
|
240
|
+
shield.sendAttributesWithCallback(screenName, data, result -> {
|
|
241
|
+
if (result instanceof Result.Failure) {
|
|
242
|
+
ShieldError error = ((Result.Failure<String>) result).getError();
|
|
243
|
+
emitEvent("error", error.getErrorMessage());
|
|
143
244
|
}
|
|
144
|
-
}
|
|
245
|
+
});
|
|
145
246
|
}
|
|
146
247
|
|
|
248
|
+
@ReactMethod
|
|
249
|
+
public void sendAttributesWithCallback(
|
|
250
|
+
String screenName,
|
|
251
|
+
ReadableMap json,
|
|
252
|
+
Callback successCallback,
|
|
253
|
+
Callback errorCallback) {
|
|
254
|
+
if (shield == null) {
|
|
255
|
+
errorCallback.invoke("Shield SDK is not initialized.");
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
147
258
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
259
|
+
Map<String, String> data = toStringMap(json);
|
|
260
|
+
shield.sendAttributesWithCallback(screenName, data, result ->
|
|
261
|
+
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> {
|
|
262
|
+
if (result instanceof Result.Success) {
|
|
263
|
+
successCallback.invoke(true);
|
|
264
|
+
} else if (result instanceof Result.Failure) {
|
|
265
|
+
ShieldError error = ((Result.Failure<String>) result).getError();
|
|
266
|
+
String errorMessage = error != null
|
|
267
|
+
? error.getErrorMessage()
|
|
268
|
+
: "Failed to send attributes.";
|
|
269
|
+
errorCallback.invoke(errorMessage);
|
|
270
|
+
}
|
|
271
|
+
})
|
|
272
|
+
);
|
|
151
273
|
}
|
|
152
274
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
275
|
+
// =========================================================================
|
|
276
|
+
// Send device signature
|
|
277
|
+
//
|
|
278
|
+
// Triggers a device signature computation for the given screen name.
|
|
279
|
+
// On success the SDK calls back with the session ID (String); the latest
|
|
280
|
+
// device result JSONObject is then retrieved via shield.getLatestDeviceResult().
|
|
281
|
+
// =========================================================================
|
|
282
|
+
|
|
283
|
+
@ReactMethod
|
|
284
|
+
public void sendDeviceSignature(
|
|
285
|
+
String screenName,
|
|
286
|
+
Callback successCallback,
|
|
287
|
+
Callback errorCallback) {
|
|
288
|
+
if (shield == null) {
|
|
289
|
+
errorCallback.invoke("Shield SDK is not initialized.");
|
|
290
|
+
return;
|
|
159
291
|
}
|
|
292
|
+
|
|
293
|
+
shield.sendDeviceSignatureWithCallback(screenName, result ->
|
|
294
|
+
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> {
|
|
295
|
+
if (result instanceof Result.Success) {
|
|
296
|
+
JSONObject json = shield.getLatestDeviceResult();
|
|
297
|
+
successCallback.invoke(json != null ? toWritableMap(json) : null);
|
|
298
|
+
} else if (result instanceof Result.Failure) {
|
|
299
|
+
ShieldError error = ((Result.Failure<String>) result).getError();
|
|
300
|
+
errorCallback.invoke(error != null
|
|
301
|
+
? error.getErrorMessage()
|
|
302
|
+
: "Failed to send device signature.");
|
|
303
|
+
}
|
|
304
|
+
})
|
|
305
|
+
);
|
|
160
306
|
}
|
|
161
307
|
|
|
308
|
+
// =========================================================================
|
|
309
|
+
// RCTEventEmitter stubs — required for compatibility on both architectures
|
|
310
|
+
// =========================================================================
|
|
311
|
+
|
|
312
|
+
@ReactMethod
|
|
313
|
+
public void addListener(String eventName) {}
|
|
314
|
+
|
|
315
|
+
@ReactMethod
|
|
316
|
+
public void removeListeners(double count) {}
|
|
317
|
+
|
|
318
|
+
// =========================================================================
|
|
319
|
+
// Module teardown
|
|
320
|
+
// =========================================================================
|
|
321
|
+
|
|
162
322
|
@Override
|
|
163
|
-
public void
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
323
|
+
public void invalidate() {
|
|
324
|
+
// Do not call super.invalidate() — ReactContextBaseJavaModule does not
|
|
325
|
+
// declare invalidate() as a concrete method in older React Native versions
|
|
326
|
+
// (it is only on the NativeModule interface), so super.invalidate() fails
|
|
327
|
+
// to compile. Our own cleanup is all that is needed here.
|
|
328
|
+
shield = null;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// =========================================================================
|
|
332
|
+
// Internal helpers
|
|
333
|
+
// =========================================================================
|
|
169
334
|
|
|
335
|
+
private void emitEvent(String eventName, Object data) {
|
|
336
|
+
reactContext
|
|
337
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
338
|
+
.emit(eventName, data);
|
|
170
339
|
}
|
|
171
340
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
HashMap<String, String> data = new HashMap<String, String>();
|
|
341
|
+
private Map<String, String> toStringMap(ReadableMap json) {
|
|
342
|
+
Map<String, String> data = new HashMap<>();
|
|
175
343
|
for (Map.Entry<String, Object> entry : json.toHashMap().entrySet()) {
|
|
176
|
-
|
|
344
|
+
if (entry.getValue() instanceof String) {
|
|
345
|
+
data.put(entry.getKey(), (String) entry.getValue());
|
|
346
|
+
}
|
|
177
347
|
}
|
|
178
|
-
|
|
348
|
+
return data;
|
|
179
349
|
}
|
|
180
350
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
351
|
+
private WritableMap toWritableMap(JSONObject jsonObject) {
|
|
352
|
+
WritableMap map = Arguments.createMap();
|
|
353
|
+
Iterator<String> keys = jsonObject.keys();
|
|
354
|
+
while (keys.hasNext()) {
|
|
355
|
+
String key = keys.next();
|
|
356
|
+
putValueInMap(map, key, jsonObject.opt(key));
|
|
357
|
+
}
|
|
358
|
+
return map;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
private WritableArray toWritableArray(JSONArray jsonArray) {
|
|
362
|
+
WritableArray array = Arguments.createArray();
|
|
363
|
+
for (int i = 0; i < jsonArray.length(); i++) {
|
|
364
|
+
pushValueInArray(array, jsonArray.opt(i));
|
|
365
|
+
}
|
|
366
|
+
return array;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
private void putValueInMap(WritableMap map, String key, Object value) {
|
|
370
|
+
if (value == null || value == JSONObject.NULL) {
|
|
371
|
+
map.putNull(key);
|
|
372
|
+
} else if (value instanceof Boolean) {
|
|
373
|
+
map.putBoolean(key, (Boolean) value);
|
|
374
|
+
} else if (value instanceof Number) {
|
|
375
|
+
map.putDouble(key, ((Number) value).doubleValue());
|
|
376
|
+
} else if (value instanceof JSONObject) {
|
|
377
|
+
map.putMap(key, toWritableMap((JSONObject) value));
|
|
378
|
+
} else if (value instanceof JSONArray) {
|
|
379
|
+
map.putArray(key, toWritableArray((JSONArray) value));
|
|
188
380
|
} else {
|
|
189
|
-
|
|
190
|
-
String errorMessage = (error != null) ? error.getMessage() : "unknown error";
|
|
191
|
-
errorCallback.invoke(errorMessage);
|
|
381
|
+
map.putString(key, String.valueOf(value));
|
|
192
382
|
}
|
|
193
|
-
}
|
|
194
|
-
@ReactMethod
|
|
195
|
-
public void addListener(String eventName) {
|
|
196
|
-
// Code to handle adding listeners
|
|
197
383
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
384
|
+
|
|
385
|
+
private void pushValueInArray(WritableArray array, Object value) {
|
|
386
|
+
if (value == null || value == JSONObject.NULL) {
|
|
387
|
+
array.pushNull();
|
|
388
|
+
} else if (value instanceof Boolean) {
|
|
389
|
+
array.pushBoolean((Boolean) value);
|
|
390
|
+
} else if (value instanceof Number) {
|
|
391
|
+
array.pushDouble(((Number) value).doubleValue());
|
|
392
|
+
} else if (value instanceof JSONObject) {
|
|
393
|
+
array.pushMap(toWritableMap((JSONObject) value));
|
|
394
|
+
} else if (value instanceof JSONArray) {
|
|
395
|
+
array.pushArray(toWritableArray((JSONArray) value));
|
|
396
|
+
} else {
|
|
397
|
+
array.pushString(String.valueOf(value));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Maps JS logLevel integer → Shield SDK LogLevel enum.
|
|
403
|
+
*
|
|
404
|
+
* JS LogLevel enum values (src/index.tsx):
|
|
405
|
+
* LogLevelVerbose = 4 → LogLevel.VERBOSE
|
|
406
|
+
* LogLevelDebug = 3 → LogLevel.DEBUG
|
|
407
|
+
* LogLevelInfo = 2 → LogLevel.INFO
|
|
408
|
+
* LogLevelNone = 1 → LogLevel.NONE (default)
|
|
409
|
+
*/
|
|
410
|
+
private LogLevel getLogLevelFromInt(int logLevel) {
|
|
411
|
+
switch (logLevel) {
|
|
412
|
+
case 4: return LogLevel.VERBOSE;
|
|
413
|
+
case 3: return LogLevel.DEBUG;
|
|
414
|
+
case 2: return LogLevel.INFO;
|
|
415
|
+
default: return LogLevel.NONE;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Maps JS environmentInfo integer → Shield SDK Environment enum.
|
|
421
|
+
*
|
|
422
|
+
* JS EnvironmentInfo enum values (src/index.tsx):
|
|
423
|
+
* EnvironmentProd = 0 → Environment.PROD (default)
|
|
424
|
+
* EnvironmentDev = 1 → Environment.DEV
|
|
425
|
+
* EnvironmentStaging = 2 → Environment.STAGING
|
|
426
|
+
*/
|
|
427
|
+
private Environment getEnvironmentFromInt(int environment) {
|
|
428
|
+
switch (environment) {
|
|
429
|
+
case 1: return Environment.DEV;
|
|
430
|
+
case 2: return Environment.STAGING;
|
|
431
|
+
default: return Environment.PROD;
|
|
432
|
+
}
|
|
202
433
|
}
|
|
203
434
|
}
|