@truewatchtech/react-native-mobile 0.3.15 → 0.3.16
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/FTMobileReactNativeSDK.podspec +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/ft/sdk/reactnative/FTMobileImpl.java +424 -5
- package/android/src/main/java/com/ft/sdk/reactnative/FTRUMImpl.java +12 -0
- package/android/src/newarch/java/com/ft/sdk/reactnative/FTMobileModule.java +23 -1
- package/android/src/oldarch/java/com/ft/sdk/reactnative/FTMobileModule.java +24 -2
- package/ios/FTMobileReactNative.h +2 -2
- package/ios/FTMobileReactNative.m +358 -4
- package/ios/FTReactNativeRUM.m +9 -0
- package/lib/commonjs/ft_logger.js +5 -2
- package/lib/commonjs/ft_logger.js.map +1 -1
- package/lib/commonjs/ft_mobile_agent.js +142 -3
- package/lib/commonjs/ft_mobile_agent.js.map +1 -1
- package/lib/commonjs/ft_rum.js +40 -13
- package/lib/commonjs/ft_rum.js.map +1 -1
- package/lib/commonjs/ft_tracing.js.map +1 -1
- package/lib/commonjs/index.js +30 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/ft_logger.js +5 -2
- package/lib/module/ft_logger.js.map +1 -1
- package/lib/module/ft_mobile_agent.js +142 -3
- package/lib/module/ft_mobile_agent.js.map +1 -1
- package/lib/module/ft_rum.js +39 -9
- package/lib/module/ft_rum.js.map +1 -1
- package/lib/module/ft_tracing.js.map +1 -1
- package/lib/module/index.js +3 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/ft_mobile_agent.d.ts +140 -2
- package/lib/typescript/ft_rum.d.ts +24 -0
- package/lib/typescript/index.d.ts +3 -3
- package/lib/typescript/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/ft_logger.tsx +6 -2
- package/src/ft_mobile_agent.tsx +217 -8
- package/src/ft_rum.tsx +66 -9
- package/src/ft_tracing.tsx +21 -2
- package/src/index.tsx +6 -5
- package/src/version.ts +1 -1
- package/android/src/main/java/com/ft/sdk/InnerClassProxy.java +0 -8
package/android/build.gradle
CHANGED
|
@@ -177,7 +177,7 @@ repositories {
|
|
|
177
177
|
dependencies {
|
|
178
178
|
// noinspection GradleDynamicVersion
|
|
179
179
|
implementation 'com.facebook.react:react-native:+'
|
|
180
|
-
implementation 'com.truewatch.ft.mobile.sdk.tracker.agent:ft-sdk:1.6.
|
|
180
|
+
implementation 'com.truewatch.ft.mobile.sdk.tracker.agent:ft-sdk:1.6.17'
|
|
181
181
|
implementation 'com.truewatch.ft.mobile.sdk.tracker.agent:ft-native:1.1.2'
|
|
182
182
|
implementation 'com.google.code.gson:gson:2.8.5'
|
|
183
183
|
}
|
|
@@ -2,23 +2,341 @@ package com.ft.sdk.reactnative;
|
|
|
2
2
|
|
|
3
3
|
import static com.ft.sdk.garble.utils.Constants.FT_LOG_DEFAULT_MEASUREMENT;
|
|
4
4
|
|
|
5
|
+
import androidx.annotation.Nullable;
|
|
6
|
+
|
|
7
|
+
import com.facebook.react.bridge.Arguments;
|
|
5
8
|
import com.facebook.react.bridge.Promise;
|
|
9
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
10
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
6
11
|
import com.facebook.react.bridge.ReadableMap;
|
|
12
|
+
import com.facebook.react.bridge.ReadableType;
|
|
13
|
+
import com.facebook.react.bridge.WritableArray;
|
|
14
|
+
import com.facebook.react.bridge.WritableMap;
|
|
15
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
7
16
|
import com.ft.sdk.DBCacheDiscard;
|
|
8
17
|
import com.ft.sdk.EnvType;
|
|
18
|
+
import com.ft.sdk.FTRemoteConfigManager;
|
|
9
19
|
import com.ft.sdk.FTSDKConfig;
|
|
10
20
|
import com.ft.sdk.FTSdk;
|
|
11
|
-
import com.ft.sdk.InnerClassProxy;
|
|
12
21
|
import com.ft.sdk.LineDataModifier;
|
|
22
|
+
import com.ft.sdk.garble.bean.RemoteConfigBean;
|
|
13
23
|
import com.ft.sdk.garble.bean.UserData;
|
|
14
24
|
import com.ft.sdk.DataModifier;
|
|
15
25
|
import com.ft.sdk.reactnative.utils.ReactNativeUtils;
|
|
16
26
|
|
|
17
27
|
import java.util.HashMap;
|
|
28
|
+
import java.util.ArrayList;
|
|
29
|
+
import java.util.List;
|
|
18
30
|
import java.util.Map;
|
|
31
|
+
import org.json.JSONArray;
|
|
32
|
+
import org.json.JSONException;
|
|
33
|
+
import org.json.JSONObject;
|
|
19
34
|
|
|
20
35
|
public class FTMobileImpl {
|
|
21
36
|
public static final String NAME = "FTMobileReactNative";
|
|
37
|
+
private static final String REMOTE_CONFIG_EVENT = "ft_remote_config_callback";
|
|
38
|
+
private final ReactApplicationContext reactContext;
|
|
39
|
+
private boolean remoteConfigurationEnabled = false;
|
|
40
|
+
private int remoteConfigMiniUpdateInterval = 12 * 60 * 60;
|
|
41
|
+
@Nullable
|
|
42
|
+
private ReadableArray remoteConfigOverrideRules;
|
|
43
|
+
|
|
44
|
+
public FTMobileImpl(ReactApplicationContext reactContext) {
|
|
45
|
+
this.reactContext = reactContext;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private static class RemoteConfigOverrideResult {
|
|
49
|
+
final RemoteConfigBean configBean;
|
|
50
|
+
final List<String> appliedRuleIds;
|
|
51
|
+
|
|
52
|
+
RemoteConfigOverrideResult(RemoteConfigBean configBean, List<String> appliedRuleIds) {
|
|
53
|
+
this.configBean = configBean;
|
|
54
|
+
this.appliedRuleIds = appliedRuleIds;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private WritableMap createRemoteConfigPayload(String triggerType,
|
|
59
|
+
boolean success,
|
|
60
|
+
@Nullable String rawJson,
|
|
61
|
+
@Nullable List<String> appliedRuleIds,
|
|
62
|
+
@Nullable String errorCode,
|
|
63
|
+
@Nullable String errorMessage) {
|
|
64
|
+
WritableMap payload = Arguments.createMap();
|
|
65
|
+
payload.putString("triggerType", triggerType);
|
|
66
|
+
payload.putBoolean("success", success);
|
|
67
|
+
payload.putString("platform", "android");
|
|
68
|
+
payload.putDouble("timestamp", System.currentTimeMillis());
|
|
69
|
+
if (rawJson != null) {
|
|
70
|
+
payload.putString("rawJson", rawJson);
|
|
71
|
+
}
|
|
72
|
+
if (appliedRuleIds != null && !appliedRuleIds.isEmpty()) {
|
|
73
|
+
WritableArray ids = Arguments.createArray();
|
|
74
|
+
for (String ruleId : appliedRuleIds) {
|
|
75
|
+
ids.pushString(ruleId);
|
|
76
|
+
}
|
|
77
|
+
payload.putArray("appliedOverrideRuleIds", ids);
|
|
78
|
+
}
|
|
79
|
+
if (errorCode != null) {
|
|
80
|
+
payload.putString("errorCode", errorCode);
|
|
81
|
+
}
|
|
82
|
+
if (errorMessage != null) {
|
|
83
|
+
payload.putString("errorMessage", errorMessage);
|
|
84
|
+
}
|
|
85
|
+
return payload;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private void emitRemoteConfigEvent(boolean success, @Nullable String rawJson,
|
|
89
|
+
@Nullable List<String> appliedRuleIds,
|
|
90
|
+
@Nullable String errorCode, @Nullable String errorMessage) {
|
|
91
|
+
if (!reactContext.hasActiveCatalystInstance()) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
reactContext
|
|
95
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
96
|
+
.emit(REMOTE_CONFIG_EVENT, createRemoteConfigPayload("auto", success, rawJson, appliedRuleIds, errorCode, errorMessage));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private RemoteConfigOverrideResult applyRemoteConfigOverrideRules(RemoteConfigBean configBean,
|
|
100
|
+
@Nullable String jsonConfig) {
|
|
101
|
+
return applyRemoteConfigOverrideRules(configBean, jsonConfig, this.remoteConfigOverrideRules);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private RemoteConfigOverrideResult applyRemoteConfigOverrideRules(RemoteConfigBean configBean,
|
|
105
|
+
@Nullable String jsonConfig,
|
|
106
|
+
@Nullable ReadableArray rules) {
|
|
107
|
+
if (configBean == null || jsonConfig == null || rules == null || rules.size() == 0) {
|
|
108
|
+
return new RemoteConfigOverrideResult(configBean, new ArrayList<>());
|
|
109
|
+
}
|
|
110
|
+
List<String> appliedRuleIds = new ArrayList<>();
|
|
111
|
+
try {
|
|
112
|
+
JSONObject jsonObject = new JSONObject(jsonConfig);
|
|
113
|
+
for (int i = 0; i < rules.size(); i++) {
|
|
114
|
+
if (rules.getType(i) != ReadableType.Map) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
ReadableMap rule = rules.getMap(i);
|
|
118
|
+
boolean enabled = !rule.hasKey("enabled") || rule.isNull("enabled") || rule.getBoolean("enabled");
|
|
119
|
+
if (!enabled) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
ReadableMap match = rule.hasKey("match") && !rule.isNull("match") ? rule.getMap("match") : null;
|
|
123
|
+
ReadableMap customKeys = match != null && match.hasKey("customKeys") && !match.isNull("customKeys")
|
|
124
|
+
? match.getMap("customKeys") : null;
|
|
125
|
+
if (customKeys == null) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
HashMap<String, Object> keyMap = customKeys.toHashMap();
|
|
129
|
+
if (keyMap.isEmpty()) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
boolean matches = true;
|
|
133
|
+
for (Map.Entry<String, Object> entry : keyMap.entrySet()) {
|
|
134
|
+
Object expectedValue = entry.getValue();
|
|
135
|
+
Object actualValue = getJsonValue(jsonObject, entry.getKey());
|
|
136
|
+
|
|
137
|
+
if (!matchesCustomKey(actualValue, expectedValue)) {
|
|
138
|
+
matches = false;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (!matches) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
ReadableMap override = rule.hasKey("override") && !rule.isNull("override") ? rule.getMap("override") : null;
|
|
146
|
+
if (override == null) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Basic configuration properties
|
|
151
|
+
if (override.hasKey("env") && !override.isNull("env")) {
|
|
152
|
+
configBean.setEnv(override.getString("env"));
|
|
153
|
+
}
|
|
154
|
+
if (override.hasKey("serviceName") && !override.isNull("serviceName")) {
|
|
155
|
+
configBean.setServiceName(override.getString("serviceName"));
|
|
156
|
+
}
|
|
157
|
+
if (override.hasKey("autoSync") && !override.isNull("autoSync")) {
|
|
158
|
+
configBean.setAutoSync(override.getBoolean("autoSync"));
|
|
159
|
+
}
|
|
160
|
+
if (override.hasKey("compressIntakeRequests") && !override.isNull("compressIntakeRequests")) {
|
|
161
|
+
configBean.setCompressIntakeRequests(override.getBoolean("compressIntakeRequests"));
|
|
162
|
+
}
|
|
163
|
+
if (override.hasKey("syncPageSize") && !override.isNull("syncPageSize")) {
|
|
164
|
+
configBean.setSyncPageSize(override.getInt("syncPageSize"));
|
|
165
|
+
}
|
|
166
|
+
if (override.hasKey("syncSleepTime") && !override.isNull("syncSleepTime")) {
|
|
167
|
+
configBean.setSyncSleepTime(override.getInt("syncSleepTime"));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Log configuration properties
|
|
171
|
+
if (override.hasKey("logSampleRate") && !override.isNull("logSampleRate")) {
|
|
172
|
+
configBean.setLogSampleRate((float) override.getDouble("logSampleRate"));
|
|
173
|
+
}
|
|
174
|
+
if (override.hasKey("logLevelFilters") && !override.isNull("logLevelFilters")) {
|
|
175
|
+
ReadableArray filtersArray = override.getArray("logLevelFilters");
|
|
176
|
+
String[] filters = new String[filtersArray.size()];
|
|
177
|
+
for (int j = 0; j < filtersArray.size(); j++) {
|
|
178
|
+
filters[j] = filtersArray.getString(j);
|
|
179
|
+
}
|
|
180
|
+
configBean.setLogLevelFilters(filters);
|
|
181
|
+
}
|
|
182
|
+
if (override.hasKey("logEnableCustomLog") && !override.isNull("logEnableCustomLog")) {
|
|
183
|
+
configBean.setLogEnableCustomLog(override.getBoolean("logEnableCustomLog"));
|
|
184
|
+
}
|
|
185
|
+
if (override.hasKey("logEnableConsoleLog") && !override.isNull("logEnableConsoleLog")) {
|
|
186
|
+
configBean.setLogEnableConsoleLog(override.getBoolean("logEnableConsoleLog"));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// RUM configuration properties
|
|
190
|
+
if (override.hasKey("rumSampleRate") && !override.isNull("rumSampleRate")) {
|
|
191
|
+
configBean.setRumSampleRate((float) override.getDouble("rumSampleRate"));
|
|
192
|
+
}
|
|
193
|
+
if (override.hasKey("rumSessionOnErrorSampleRate") && !override.isNull("rumSessionOnErrorSampleRate")) {
|
|
194
|
+
configBean.setRumSessionOnErrorSampleRate((float) override.getDouble("rumSessionOnErrorSampleRate"));
|
|
195
|
+
}
|
|
196
|
+
if (override.hasKey("rumEnableTraceUserAction") && !override.isNull("rumEnableTraceUserAction")) {
|
|
197
|
+
configBean.setRumEnableTraceUserAction(override.getBoolean("rumEnableTraceUserAction"));
|
|
198
|
+
}
|
|
199
|
+
if (override.hasKey("rumEnableTraceUserView") && !override.isNull("rumEnableTraceUserView")) {
|
|
200
|
+
configBean.setRumEnableTraceUserView(override.getBoolean("rumEnableTraceUserView"));
|
|
201
|
+
}
|
|
202
|
+
if (override.hasKey("rumEnableTraceUserResource") && !override.isNull("rumEnableTraceUserResource")) {
|
|
203
|
+
configBean.setRumEnableTraceUserResource(override.getBoolean("rumEnableTraceUserResource"));
|
|
204
|
+
}
|
|
205
|
+
if (override.hasKey("rumEnableResourceHostIP") && !override.isNull("rumEnableResourceHostIP")) {
|
|
206
|
+
configBean.setRumEnableResourceHostIP(override.getBoolean("rumEnableResourceHostIP"));
|
|
207
|
+
}
|
|
208
|
+
if (override.hasKey("rumEnableTrackAppUIBlock") && !override.isNull("rumEnableTrackAppUIBlock")) {
|
|
209
|
+
configBean.setRumEnableTrackAppUIBlock(override.getBoolean("rumEnableTrackAppUIBlock"));
|
|
210
|
+
}
|
|
211
|
+
if (override.hasKey("rumBlockDurationMs") && !override.isNull("rumBlockDurationMs")) {
|
|
212
|
+
configBean.setRumBlockDurationMs((long) override.getInt("rumBlockDurationMs"));
|
|
213
|
+
}
|
|
214
|
+
if (override.hasKey("rumEnableTrackAppCrash") && !override.isNull("rumEnableTrackAppCrash")) {
|
|
215
|
+
configBean.setRumEnableTrackAppCrash(override.getBoolean("rumEnableTrackAppCrash"));
|
|
216
|
+
}
|
|
217
|
+
if (override.hasKey("rumEnableTrackAppANR") && !override.isNull("rumEnableTrackAppANR")) {
|
|
218
|
+
configBean.setRumEnableTrackAppANR(override.getBoolean("rumEnableTrackAppANR"));
|
|
219
|
+
}
|
|
220
|
+
if (override.hasKey("rumEnableTraceWebView") && !override.isNull("rumEnableTraceWebView")) {
|
|
221
|
+
configBean.setRumEnableTraceWebView(override.getBoolean("rumEnableTraceWebView"));
|
|
222
|
+
}
|
|
223
|
+
if (override.hasKey("rumAllowWebViewHost") && !override.isNull("rumAllowWebViewHost")) {
|
|
224
|
+
ReadableArray hostsArray = override.getArray("rumAllowWebViewHost");
|
|
225
|
+
String[] hosts = new String[hostsArray.size()];
|
|
226
|
+
for (int j = 0; j < hostsArray.size(); j++) {
|
|
227
|
+
hosts[j] = hostsArray.getString(j);
|
|
228
|
+
}
|
|
229
|
+
configBean.setRumAllowWebViewHost(hosts);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Trace configuration properties
|
|
233
|
+
if (override.hasKey("traceSampleRate") && !override.isNull("traceSampleRate")) {
|
|
234
|
+
configBean.setTraceSampleRate((float) override.getDouble("traceSampleRate"));
|
|
235
|
+
}
|
|
236
|
+
if (override.hasKey("traceEnableAutoTrace") && !override.isNull("traceEnableAutoTrace")) {
|
|
237
|
+
configBean.setTraceEnableAutoTrace(override.getBoolean("traceEnableAutoTrace"));
|
|
238
|
+
}
|
|
239
|
+
if (override.hasKey("traceType") && !override.isNull("traceType")) {
|
|
240
|
+
configBean.setTraceType(override.getString("traceType"));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
String ruleId = rule.hasKey("id") && !rule.isNull("id") ? rule.getString("id") : null;
|
|
244
|
+
appliedRuleIds.add(ruleId != null ? ruleId : "rule_" + i);
|
|
245
|
+
}
|
|
246
|
+
} catch (JSONException ignored) {
|
|
247
|
+
}
|
|
248
|
+
return new RemoteConfigOverrideResult(configBean, appliedRuleIds);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private Object getJsonValue(JSONObject jsonObject, String key) {
|
|
252
|
+
if (!jsonObject.has(key)) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
Object value = jsonObject.get(key);
|
|
257
|
+
if (value == JSONObject.NULL) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
return value;
|
|
261
|
+
} catch (JSONException e) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private boolean isEqualValue(Object actual, Object expected) {
|
|
267
|
+
if (actual == null && expected == null) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
if (actual == null || expected == null) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (actual instanceof String actualString) {
|
|
275
|
+
Object normalizedActual = parseJsonStringIfNeeded(actualString);
|
|
276
|
+
if (normalizedActual != actual) {
|
|
277
|
+
return isEqualValue(normalizedActual, expected);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Handle number comparison
|
|
282
|
+
if (actual instanceof Number && expected instanceof Number) {
|
|
283
|
+
return ((Number) actual).doubleValue() == ((Number) expected).doubleValue();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Handle string comparison
|
|
287
|
+
if (actual instanceof String && expected instanceof String) {
|
|
288
|
+
return actual.equals(expected);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Handle boolean comparison (JSON booleans are represented as Boolean in Java)
|
|
292
|
+
if (actual instanceof Boolean && expected instanceof Boolean) {
|
|
293
|
+
return actual.equals(expected);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Fallback to string comparison
|
|
297
|
+
return actual.toString().equals(expected.toString());
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private boolean matchesCustomKey(Object actual, Object expected) {
|
|
301
|
+
if (expected instanceof Map<?, ?> expectedMap && expectedMap.containsKey("contains")) {
|
|
302
|
+
return containsValue(actual, expectedMap.get("contains"));
|
|
303
|
+
}
|
|
304
|
+
return isEqualValue(actual, expected);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
private boolean containsValue(Object actual, Object expectedValue) {
|
|
308
|
+
Object normalizedActual = actual instanceof String actualString
|
|
309
|
+
? parseJsonStringIfNeeded(actualString)
|
|
310
|
+
: actual;
|
|
311
|
+
|
|
312
|
+
if (normalizedActual instanceof JSONArray actualArray) {
|
|
313
|
+
try {
|
|
314
|
+
for (int i = 0; i < actualArray.length(); i++) {
|
|
315
|
+
if (isEqualValue(actualArray.get(i), expectedValue)) {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
} catch (JSONException ignored) {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return isEqualValue(normalizedActual, expectedValue);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
private Object parseJsonStringIfNeeded(String value) {
|
|
327
|
+
String trimmedValue = value.trim();
|
|
328
|
+
if (trimmedValue.length() < 2) {
|
|
329
|
+
return value;
|
|
330
|
+
}
|
|
331
|
+
try {
|
|
332
|
+
if (trimmedValue.startsWith("[") && trimmedValue.endsWith("]")) {
|
|
333
|
+
return new JSONArray(trimmedValue);
|
|
334
|
+
}
|
|
335
|
+
} catch (JSONException ignored) {
|
|
336
|
+
return value;
|
|
337
|
+
}
|
|
338
|
+
return value;
|
|
339
|
+
}
|
|
22
340
|
|
|
23
341
|
public void sdkConfig(ReadableMap context, Promise promise) {
|
|
24
342
|
Map<String, Object> map = context.toHashMap();
|
|
@@ -37,9 +355,12 @@ public class FTMobileImpl {
|
|
|
37
355
|
Boolean enableLimitWithDbSize = (Boolean) map.get("enableLimitWithDbSize");
|
|
38
356
|
Long dbCacheLimit = ReactNativeUtils.convertToNativeLong(map.get("dbCacheLimit"));
|
|
39
357
|
Integer dbDiscardStrategy = ReactNativeUtils.convertToNativeInt(map.get("dbDiscardStrategy"));
|
|
40
|
-
String sdkPkgInfo = (String)map.get("pkgInfo");
|
|
41
358
|
Map<String, Object> dataModifier = (Map<String, Object>) map.get("dataModifier");
|
|
42
359
|
Map<String, Map<String,Object>> lineDataModifier = (Map<String, Map<String,Object>>) map.get("lineDataModifier");
|
|
360
|
+
Boolean remoteConfiguration = (Boolean) map.get("remoteConfiguration");
|
|
361
|
+
Integer remoteConfigMiniUpdateInterval = ReactNativeUtils.convertToNativeInt(map.get("remoteConfigMiniUpdateInterval"));
|
|
362
|
+
this.remoteConfigOverrideRules = context.hasKey("remoteConfigOverrideRules")
|
|
363
|
+
? context.getArray("remoteConfigOverrideRules") : null;
|
|
43
364
|
|
|
44
365
|
FTSDKConfig sdkConfig = (datakitUrl != null)
|
|
45
366
|
? FTSDKConfig.builder(datakitUrl)
|
|
@@ -103,9 +424,6 @@ public class FTMobileImpl {
|
|
|
103
424
|
sdkConfig.setDbCacheDiscard(dbCacheDiscard);
|
|
104
425
|
}
|
|
105
426
|
|
|
106
|
-
if(sdkPkgInfo!=null){
|
|
107
|
-
InnerClassProxy.addPkgInfo(sdkConfig,"reactnative",sdkPkgInfo);
|
|
108
|
-
}
|
|
109
427
|
if (dataModifier != null) {
|
|
110
428
|
sdkConfig.setDataModifier(new DataModifier() {
|
|
111
429
|
@Override
|
|
@@ -127,6 +445,40 @@ public class FTMobileImpl {
|
|
|
127
445
|
}
|
|
128
446
|
}
|
|
129
447
|
);
|
|
448
|
+
}
|
|
449
|
+
if (remoteConfiguration != null) {
|
|
450
|
+
sdkConfig.setRemoteConfiguration(remoteConfiguration);
|
|
451
|
+
}
|
|
452
|
+
remoteConfigurationEnabled = sdkConfig.isRemoteConfiguration();
|
|
453
|
+
if (remoteConfigMiniUpdateInterval != null) {
|
|
454
|
+
sdkConfig.setRemoteConfigMiniUpdateInterval(remoteConfigMiniUpdateInterval);
|
|
455
|
+
this.remoteConfigMiniUpdateInterval = remoteConfigMiniUpdateInterval;
|
|
456
|
+
} else {
|
|
457
|
+
this.remoteConfigMiniUpdateInterval = sdkConfig.getRemoteConfigMiniUpdateInterval();
|
|
458
|
+
}
|
|
459
|
+
if (remoteConfigurationEnabled) {
|
|
460
|
+
sdkConfig.setRemoteConfigurationCallBack(new FTRemoteConfigManager.FetchResult() {
|
|
461
|
+
private String rawJson;
|
|
462
|
+
private List<String> appliedRuleIds = new ArrayList<>();
|
|
463
|
+
|
|
464
|
+
@Override
|
|
465
|
+
public RemoteConfigBean onConfigSuccessFetched(RemoteConfigBean configBean, String jsonConfig) {
|
|
466
|
+
rawJson = jsonConfig;
|
|
467
|
+
RemoteConfigOverrideResult result = applyRemoteConfigOverrideRules(configBean, jsonConfig);
|
|
468
|
+
appliedRuleIds = result.appliedRuleIds;
|
|
469
|
+
emitRemoteConfigEvent(true, configBean.toJsonString(), appliedRuleIds, null, null);
|
|
470
|
+
return result.configBean;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
@Override
|
|
474
|
+
public void onResult(boolean success) {
|
|
475
|
+
if (!success) {
|
|
476
|
+
emitRemoteConfigEvent(false, rawJson, appliedRuleIds, "FETCH_FAILED", "Remote config update failed");
|
|
477
|
+
}
|
|
478
|
+
rawJson = null;
|
|
479
|
+
appliedRuleIds = new ArrayList<>();
|
|
480
|
+
}
|
|
481
|
+
});
|
|
130
482
|
}
|
|
131
483
|
FTSdk.install(sdkConfig);
|
|
132
484
|
// LogUtils.d("configCheck","sdkConfig:"+new Gson().toJson(sdkConfig));
|
|
@@ -195,4 +547,71 @@ public class FTMobileImpl {
|
|
|
195
547
|
FTSdk.clearAllData();
|
|
196
548
|
promise.resolve(null);
|
|
197
549
|
}
|
|
550
|
+
|
|
551
|
+
public void updateRemoteConfig(Promise promise) {
|
|
552
|
+
if (!remoteConfigurationEnabled) {
|
|
553
|
+
promise.reject("E_REMOTE_CONFIG_DISABLED", "Remote configuration is not enabled.");
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
FTSdk.updateRemoteConfig(remoteConfigMiniUpdateInterval, new FTRemoteConfigManager.FetchResult() {
|
|
557
|
+
private String rawJson;
|
|
558
|
+
private List<String> appliedRuleIds = new ArrayList<>();
|
|
559
|
+
|
|
560
|
+
@Override
|
|
561
|
+
public RemoteConfigBean onConfigSuccessFetched(RemoteConfigBean configBean, String jsonConfig) {
|
|
562
|
+
rawJson = jsonConfig;
|
|
563
|
+
RemoteConfigOverrideResult result = applyRemoteConfigOverrideRules(configBean, jsonConfig);
|
|
564
|
+
appliedRuleIds = result.appliedRuleIds;
|
|
565
|
+
promise.resolve(createRemoteConfigPayload("manual", true, configBean.toJsonString(), appliedRuleIds, null, null));
|
|
566
|
+
return result.configBean;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
@Override
|
|
570
|
+
public void onResult(boolean success) {
|
|
571
|
+
if (!success) {
|
|
572
|
+
promise.reject("E_REMOTE_CONFIG_UPDATE_FAILED", "Remote config update failed");
|
|
573
|
+
} else if (rawJson == null) {
|
|
574
|
+
promise.resolve(createRemoteConfigPayload("manual", true, null, appliedRuleIds, null, null));
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
public void updateRemoteConfigWithMiniUpdateInterval(int interval, @Nullable ReadableArray rules, Promise promise) {
|
|
581
|
+
if (!remoteConfigurationEnabled) {
|
|
582
|
+
promise.reject("E_REMOTE_CONFIG_DISABLED", "Remote configuration is not enabled.");
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
FTSdk.updateRemoteConfig(interval, new FTRemoteConfigManager.FetchResult() {
|
|
586
|
+
private String rawJson;
|
|
587
|
+
private List<String> appliedRuleIds = new ArrayList<>();
|
|
588
|
+
|
|
589
|
+
@Override
|
|
590
|
+
public RemoteConfigBean onConfigSuccessFetched(RemoteConfigBean configBean, String jsonConfig) {
|
|
591
|
+
rawJson = jsonConfig;
|
|
592
|
+
ReadableArray rulesToApply = rules != null && rules.size() > 0 ? rules : remoteConfigOverrideRules;
|
|
593
|
+
RemoteConfigOverrideResult result = applyRemoteConfigOverrideRules(configBean, jsonConfig, rulesToApply);
|
|
594
|
+
appliedRuleIds = result.appliedRuleIds;
|
|
595
|
+
promise.resolve(createRemoteConfigPayload("manual", true, configBean.toJsonString(), appliedRuleIds, null, null));
|
|
596
|
+
return result.configBean;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
@Override
|
|
600
|
+
public void onResult(boolean success) {
|
|
601
|
+
if (!success) {
|
|
602
|
+
promise.reject("E_REMOTE_CONFIG_UPDATE_FAILED", "Remote config update failed");
|
|
603
|
+
} else if (rawJson == null) {
|
|
604
|
+
promise.resolve(createRemoteConfigPayload("manual", true, null, appliedRuleIds, null, null));
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
public void addListener(String eventName) {
|
|
611
|
+
// Required for NativeEventEmitter. No-op because native does not need listener bookkeeping.
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
public void removeListeners(double count) {
|
|
615
|
+
// Required for NativeEventEmitter. No-op because native does not need listener bookkeeping.
|
|
616
|
+
}
|
|
198
617
|
}
|
|
@@ -15,6 +15,7 @@ import com.ft.sdk.garble.bean.NetStatusBean;
|
|
|
15
15
|
import com.ft.sdk.garble.bean.ResourceParams;
|
|
16
16
|
import com.ft.sdk.reactnative.utils.ReactNativeUtils;
|
|
17
17
|
|
|
18
|
+
import java.util.ArrayList;
|
|
18
19
|
import java.util.HashMap;
|
|
19
20
|
import java.util.Map;
|
|
20
21
|
|
|
@@ -44,6 +45,8 @@ public class FTRUMImpl {
|
|
|
44
45
|
Map<String, Object> globalContext = (Map<String, Object>) map.get("globalContext");
|
|
45
46
|
Integer rumCacheLimitCount = ReactNativeUtils.convertToNativeInt(map.get("rumCacheLimitCount"));
|
|
46
47
|
Integer rumDiscardStrategy = ReactNativeUtils.convertToNativeInt(map.get("rumDiscardStrategy"));
|
|
48
|
+
Boolean enableTraceWebView = (Boolean) map.get("enableTraceWebView");
|
|
49
|
+
ArrayList<String> allowWebViewHost = (ArrayList<String>) map.get("allowWebViewHost");
|
|
47
50
|
|
|
48
51
|
FTRUMConfig rumConfig = new FTRUMConfig().setRumAppId(rumAppId);
|
|
49
52
|
if (sampleRate != null) {
|
|
@@ -122,6 +125,15 @@ public class FTRUMImpl {
|
|
|
122
125
|
}
|
|
123
126
|
rumConfig.setRumCacheDiscardStrategy(rumCacheDiscard);
|
|
124
127
|
}
|
|
128
|
+
if (enableTraceWebView != null) {
|
|
129
|
+
rumConfig.setEnableTraceWebView(enableTraceWebView);
|
|
130
|
+
}
|
|
131
|
+
if (allowWebViewHost != null) {
|
|
132
|
+
String[] allowWebViewHostArr = new String[allowWebViewHost.size()];
|
|
133
|
+
allowWebViewHost.toArray(allowWebViewHostArr);
|
|
134
|
+
rumConfig.setAllowWebViewHost(allowWebViewHostArr);
|
|
135
|
+
}
|
|
136
|
+
|
|
125
137
|
FTSdk.initRUMWithConfig(rumConfig);
|
|
126
138
|
//LogUtils.d("configCheck","rumConfig:"+new Gson().toJson(rumConfig));
|
|
127
139
|
promise.resolve(null);
|
|
@@ -11,10 +11,11 @@ import com.facebook.react.bridge.ReadableMap;
|
|
|
11
11
|
@ReactModule(name = FTMobileModule.NAME)
|
|
12
12
|
public class FTMobileModule extends NativeFTMobileSpec {
|
|
13
13
|
public static final String NAME = FTMobileImpl.NAME;
|
|
14
|
-
private final FTMobileImpl impl
|
|
14
|
+
private final FTMobileImpl impl;
|
|
15
15
|
|
|
16
16
|
public FTMobileModule(ReactApplicationContext reactContext) {
|
|
17
17
|
super(reactContext);
|
|
18
|
+
impl = new FTMobileImpl(reactContext);
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
@Override
|
|
@@ -66,4 +67,25 @@ public class FTMobileModule extends NativeFTMobileSpec {
|
|
|
66
67
|
public void clearAllData(Promise promise) {
|
|
67
68
|
impl.clearAllData(promise);
|
|
68
69
|
}
|
|
70
|
+
|
|
71
|
+
@ReactMethod
|
|
72
|
+
public void updateRemoteConfig(Promise promise) {
|
|
73
|
+
impl.updateRemoteConfig(promise);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@ReactMethod
|
|
77
|
+
public void updateRemoteConfigWithMiniUpdateInterval(int interval, @Nullable ReadableArray rules, Promise promise) {
|
|
78
|
+
impl.updateRemoteConfigWithMiniUpdateInterval(interval, rules, promise);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@ReactMethod
|
|
82
|
+
public void addListener(String eventName) {
|
|
83
|
+
impl.addListener(eventName);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@ReactMethod
|
|
87
|
+
public void removeListeners(double count) {
|
|
88
|
+
impl.removeListeners(count);
|
|
89
|
+
}
|
|
90
|
+
|
|
69
91
|
}
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
package com.ft.sdk.reactnative;
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
4
5
|
|
|
5
6
|
import com.facebook.react.bridge.Promise;
|
|
6
7
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
8
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
8
9
|
import com.facebook.react.bridge.ReactMethod;
|
|
10
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
9
11
|
import com.facebook.react.bridge.ReadableMap;
|
|
10
12
|
|
|
11
13
|
public class FTMobileModule extends ReactContextBaseJavaModule {
|
|
14
|
+
private final FTMobileImpl impl;
|
|
12
15
|
|
|
13
16
|
public FTMobileModule(ReactApplicationContext reactContext) {
|
|
14
17
|
super(reactContext);
|
|
18
|
+
impl = new FTMobileImpl(reactContext);
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
private final FTMobileImpl impl = new FTMobileImpl();
|
|
18
|
-
|
|
19
21
|
@ReactMethod
|
|
20
22
|
public void sdkConfig(ReadableMap context, Promise promise) {
|
|
21
23
|
impl.sdkConfig(context, promise);
|
|
@@ -61,6 +63,26 @@ public class FTMobileModule extends ReactContextBaseJavaModule {
|
|
|
61
63
|
impl.clearAllData(promise);
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
@ReactMethod
|
|
67
|
+
public void updateRemoteConfig(Promise promise) {
|
|
68
|
+
impl.updateRemoteConfig(promise);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@ReactMethod
|
|
72
|
+
public void updateRemoteConfigWithMiniUpdateInterval(int interval, @Nullable ReadableArray rules, Promise promise) {
|
|
73
|
+
impl.updateRemoteConfigWithMiniUpdateInterval(interval, rules, promise);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@ReactMethod
|
|
77
|
+
public void addListener(String eventName) {
|
|
78
|
+
impl.addListener(eventName);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@ReactMethod
|
|
82
|
+
public void removeListeners(double count) {
|
|
83
|
+
impl.removeListeners(count);
|
|
84
|
+
}
|
|
85
|
+
|
|
64
86
|
@NonNull
|
|
65
87
|
@Override
|
|
66
88
|
public String getName() {
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
#import <Foundation/Foundation.h>
|
|
10
|
-
#import <React/
|
|
10
|
+
#import <React/RCTEventEmitter.h>
|
|
11
11
|
|
|
12
12
|
NS_ASSUME_NONNULL_BEGIN
|
|
13
13
|
|
|
14
|
-
@interface FTMobileReactNative :
|
|
14
|
+
@interface FTMobileReactNative : RCTEventEmitter<RCTBridgeModule>
|
|
15
15
|
|
|
16
16
|
@end
|
|
17
17
|
|