klaritics-react-native-sdk 1.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.
@@ -0,0 +1,324 @@
1
+ package com.deeptaai.reactnativesdk;
2
+
3
+ import android.content.Context;
4
+
5
+ import androidx.annotation.NonNull;
6
+
7
+ import com.deeptaai.klaritics.Klaritics;
8
+ import com.deeptaai.klaritics.KlariticsConfig;
9
+ import com.deeptaai.klaritics.Attributes;
10
+ import com.deeptaai.klaritics.EventListener;
11
+ import com.deeptaai.klaritics.SDKController;
12
+ import com.deeptaai.klaritics.models.BaseAnthraEvent;
13
+ import com.deeptaai.klaritics.models.NavigationEvent;
14
+ import com.deeptaai.klaritics.utils.Logger;
15
+ import com.facebook.react.bridge.ReactApplicationContext;
16
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
17
+ import com.facebook.react.bridge.ReactMethod;
18
+ import com.facebook.react.bridge.ReadableArray;
19
+ import com.facebook.react.bridge.ReadableMap;
20
+ import com.facebook.react.bridge.ReadableMapKeySetIterator;
21
+ import com.facebook.react.bridge.ReadableType;
22
+ import com.facebook.react.module.annotations.ReactModule;
23
+ import com.facebook.react.bridge.Callback;
24
+ import com.facebook.react.modules.core.DeviceEventManagerModule;
25
+ import com.facebook.react.bridge.WritableMap;
26
+ import com.facebook.react.bridge.Arguments;
27
+ import java.lang.reflect.Method;
28
+ import java.util.HashMap;
29
+ import java.util.Map;
30
+
31
+ import static com.deeptaai.klaritics.Constants.BACKGROUND;
32
+ import static com.deeptaai.klaritics.Constants.FOREGROUND;
33
+ import static com.deeptaai.klaritics.Constants.SYSTEM_EVENTS;
34
+
35
+ @ReactModule(name = KlariticsModule.NAME)
36
+ public class KlariticsModule extends ReactContextBaseJavaModule implements EventListener {
37
+ public static final String NAME = "Klaritics";
38
+ private static final String TAG = "Klaritics";
39
+
40
+ private NavigationEvent navigationEvent;
41
+ private String prevScreenName;
42
+
43
+ public KlariticsModule(ReactApplicationContext reactContext) {
44
+ super(reactContext);
45
+
46
+ SDKController controller = SDKController.getInstance();
47
+
48
+ controller.markAsReactNative();
49
+ controller.registerToEvent(SYSTEM_EVENTS, this);
50
+ }
51
+
52
+ @Override
53
+ @NonNull
54
+ public String getName() {
55
+ return NAME;
56
+ }
57
+
58
+ @ReactMethod
59
+ public void setup(String appId, String host) {
60
+ if (appId == null || appId.trim().equals("")) {
61
+ Logger.e(TAG, "App ID cannot be empty or null", null);
62
+ return;
63
+ }
64
+ if (host == null || host.trim().equals("")) {
65
+ Logger.e(TAG, "Host cannot be empty or null", null);
66
+ return;
67
+ }
68
+ KlariticsConfig config = new KlariticsConfig(appId, host);
69
+ Klaritics.setup(getReactApplicationContext().getApplicationContext(), config);
70
+ }
71
+
72
+ @ReactMethod
73
+ public void setUserIdentifier(String user) {
74
+ Klaritics.setUserIdentifier(user);
75
+ }
76
+
77
+ @ReactMethod
78
+ public void setUserCustomInfo(ReadableMap info) {
79
+ if (info == null) {
80
+ return;
81
+ }
82
+
83
+ Klaritics.setUserCustomInfo(attributesFromReadableMap(info));
84
+ }
85
+
86
+ @ReactMethod
87
+ public void logAppEvent(String event, ReadableMap additionalInfo, boolean isAggregate) {
88
+ if (event == null || event.trim().equals("")) {
89
+ Logger.e(TAG, "Name cannot be empty or null", null);
90
+ return;
91
+ }
92
+ Klaritics.logAppEvent(event, attributesFromReadableMap(additionalInfo), isAggregate);
93
+ }
94
+
95
+ @ReactMethod
96
+ public void logMetaEvent(String category, String event, ReadableMap attributes) {
97
+ if (event == null || event.trim().equals("")) {
98
+ Logger.e(TAG, "Name cannot be empty or null", null);
99
+ return;
100
+ }
101
+ Klaritics.logMetaEvent(category, event, attributesFromReadableMap(attributes));
102
+ }
103
+
104
+ @ReactMethod
105
+ public void logClientEvent(String eventName, ReadableMap attributes) {
106
+ if (eventName == null || eventName.trim().equals("")) {
107
+ Logger.e(TAG, "Name cannot be empty or null", null);
108
+ return;
109
+ }
110
+
111
+ Klaritics.logClientEvent(eventName, attributesFromReadableMap(attributes));
112
+ }
113
+
114
+ @ReactMethod
115
+ public void setSessionCustomInfo(ReadableMap info) {
116
+ if (info == null) {
117
+ return;
118
+ }
119
+ Klaritics.setSessionCustomInfo(attributesFromReadableMap(info));
120
+ }
121
+
122
+ @ReactMethod
123
+ public void handlePushNotification(ReadableMap map) {
124
+ if (map == null) {
125
+ return;
126
+ }
127
+
128
+ ReadableMapKeySetIterator iterator = map.keySetIterator();
129
+
130
+ Map<String, String> data = new HashMap<>();
131
+ while (iterator.hasNextKey()) {
132
+ String key = iterator.nextKey();
133
+ data.put(key, map.getString(key));
134
+ }
135
+
136
+ try {
137
+ Class<?> pushAPIClass = Class.forName("com.anthra.androidsdk.plugins.push.v2.anthraPushAPI");
138
+ Method handleMethod = pushAPIClass.getDeclaredMethod("handleNotification", Map.class, Context.class);
139
+ handleMethod.invoke(null, data, getReactApplicationContext());
140
+ } catch (Exception e) {
141
+ Logger.e(TAG, "Failed to handle push notification: " + e.getMessage(), null);
142
+ }
143
+ }
144
+
145
+ @ReactMethod
146
+ public void logNavigationEvent(String screenName) {
147
+ double currentTime = SDKController.getInstance().getCurrentTime();
148
+ if (navigationEvent != null) {
149
+ // Update the duration for already logged navigation event and save it
150
+ navigationEvent.setDuration(currentTime - navigationEvent.getJSONData().optDouble("transition_time"));
151
+ SDKController.getInstance().saveEvent(navigationEvent);
152
+ }
153
+
154
+ // Create new navigation event with given Screen name
155
+ navigationEvent = new NavigationEvent(screenName, currentTime);
156
+ navigationEvent.setScreenName(screenName);
157
+ }
158
+
159
+ @ReactMethod
160
+ public void trackScreen(String screenName) {
161
+ Klaritics.trackScreen(screenName);
162
+ }
163
+
164
+ @ReactMethod
165
+ public void registerSimpleNotification(String notification, String key) {
166
+ if ((null != notification) && (null != key)) {
167
+ Klaritics.registerSimpleNotification(notification, key, arg -> {
168
+ WritableMap params = Arguments.createMap();
169
+ params.putString("key", arg);
170
+ params.putString("notification",notification);
171
+ this.getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(notification,params);
172
+ });
173
+ } else {
174
+ Logger.e(TAG, "Invalid Arguments", null);
175
+ }
176
+ }
177
+
178
+ // @ReactMethod
179
+ // public void registerSimpleNotification(String notification, Callback callback) {
180
+ // if ((null != notification) && (null != callback)) {
181
+ // Runnable task = () -> { callback.invoke(); };
182
+ // anthraSDK.registerSimpleNotification(notification, task);
183
+ // } else {
184
+ // Logger.e(TAG, "Invalid Arguments", null);
185
+ // }
186
+ // }
187
+ //
188
+ // @ReactMethod
189
+ // public void unregisterSimpleNotification(String notification) {
190
+ // if (null != notification) {
191
+ // anthraSDK.unregisterSimpleNotification(notification);
192
+ // } else {
193
+ // Logger.e(TAG, "Invalid Arguments", null);
194
+ // }
195
+ // }
196
+ //
197
+ // @ReactMethod
198
+ // public void registerSimpleNotification(String notification, String key, Callback callback) {
199
+ // if ((null != notification) && (null != callback) && (null != key)) {
200
+ // anthraSDK.registerSimpleNotification(notification, key, arg -> callback.invoke(arg));
201
+ // } else {
202
+ // Logger.e(TAG, "Invalid Arguments", null);
203
+ // }
204
+ // }
205
+
206
+ @ReactMethod
207
+ public void unregisterSimpleNotification(String notification, String key) {
208
+ if ((null != notification) && (null != key)) {
209
+ Klaritics.unregisterSimpleNotification(notification,key);
210
+ } else {
211
+ Logger.e(TAG, "Invalid Arguments", null);
212
+ }
213
+ }
214
+
215
+ @ReactMethod
216
+ public void setAnthraDynamicConfig(String key, String value) {
217
+ if ((null != key) && (null != value)) {
218
+ Klaritics.setAnthraDynamicConfig(key,value);
219
+ } else {
220
+ Logger.e(TAG, "Invalid Arguments", null);
221
+ }
222
+ }
223
+
224
+ @Override
225
+ public void onEvent(BaseAnthraEvent event) {
226
+ if (event.getEventType().equals(SYSTEM_EVENTS)) {
227
+ String eventName = event.getEventName();
228
+ if (eventName.equals(FOREGROUND)) {
229
+ onBecameForeground();
230
+ } else if (eventName.equals(BACKGROUND)) {
231
+ onBecameBackground();
232
+ } else {
233
+ Logger.e(TAG, "Unknown event");
234
+ }
235
+ }
236
+ }
237
+
238
+ private void onBecameForeground() {
239
+ // This property is null when the app is opened first time in this session
240
+ // This property will be set, if application moves to background at least once
241
+
242
+ // Create new navigation item
243
+ if (prevScreenName != null) {
244
+ navigationEvent = new NavigationEvent(prevScreenName, SDKController.getInstance().getCurrentTime());
245
+ navigationEvent.setScreenName(prevScreenName);
246
+ }
247
+ }
248
+
249
+ private void onBecameBackground() {
250
+ if (navigationEvent != null) {
251
+ // save the last navigation event held in memory
252
+ navigationEvent.setDuration(SDKController.getInstance().getCurrentTime() - navigationEvent.getJSONData().optDouble("transition_time"));
253
+ SDKController.getInstance().saveEvent(navigationEvent);
254
+
255
+ // Store the current saved navigation ID to log navigationEvent when app comes to foreground
256
+ prevScreenName = navigationEvent.getEventName();
257
+ }
258
+ }
259
+
260
+ // Helper method
261
+ private Attributes attributesFromReadableMap(ReadableMap infoMap) {
262
+ if (infoMap == null) return null;
263
+
264
+ Attributes attributes = new Attributes();
265
+
266
+ ReadableMapKeySetIterator iterator = infoMap.keySetIterator();
267
+
268
+ while (iterator.hasNextKey()) {
269
+ try {
270
+ String key = iterator.nextKey();
271
+ ReadableType readableType = infoMap.getType(key);
272
+
273
+ switch (readableType) {
274
+ case String:
275
+ attributes.putAttribute(key, infoMap.getString(key));
276
+ break;
277
+ case Number:
278
+ attributes.putAttribute(key, infoMap.getDouble(key));
279
+ break;
280
+ case Array:
281
+ convertArray(attributes, key, infoMap.getArray(key));
282
+ break;
283
+ case Boolean:
284
+ attributes.putAttribute(key, infoMap.getBoolean(key));
285
+ break;
286
+ default:
287
+ Logger.e(TAG, "Unknown type " + readableType, null);
288
+ break;
289
+ }
290
+ } catch (Throwable t) {
291
+ String message = t.getMessage();
292
+ Logger.e(TAG, message == null ? "" : message);
293
+ }
294
+ }
295
+ return attributes;
296
+ }
297
+
298
+ private void convertArray(Attributes attributes, String key, ReadableArray jsonArray) {
299
+ if (jsonArray == null) {
300
+ return;
301
+ }
302
+
303
+ int length = jsonArray.size();
304
+ switch (jsonArray.getType(0)) {
305
+ case Number:
306
+ double[] array = new double[length];
307
+ for (int index = 0; index < length; index++) {
308
+ array[index] = jsonArray.getDouble(index);
309
+ }
310
+ attributes.putAttribute(key, array);
311
+ break;
312
+ case String:
313
+ String[] strArray = new String[length];
314
+ for (int index = 0; index < length; index++) {
315
+ strArray[index] = jsonArray.getString(index);
316
+ }
317
+ attributes.putAttribute(key, strArray);
318
+ break;
319
+ default:
320
+ Logger.e(TAG, "Unknown type", null);
321
+ break;
322
+ }
323
+ }
324
+ }
@@ -0,0 +1,28 @@
1
+ package com.deeptaai.reactnativesdk;
2
+
3
+ import androidx.annotation.NonNull;
4
+
5
+ import com.facebook.react.ReactPackage;
6
+ import com.facebook.react.bridge.NativeModule;
7
+ import com.facebook.react.bridge.ReactApplicationContext;
8
+ import com.facebook.react.uimanager.ViewManager;
9
+
10
+ import java.util.ArrayList;
11
+ import java.util.Collections;
12
+ import java.util.List;
13
+
14
+ public class KlariticsPackage implements ReactPackage {
15
+ @NonNull
16
+ @Override
17
+ public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
18
+ List<NativeModule> modules = new ArrayList<>();
19
+ modules.add(new KlariticsModule(reactContext));
20
+ return modules;
21
+ }
22
+
23
+ @NonNull
24
+ @Override
25
+ public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
26
+ return Collections.emptyList();
27
+ }
28
+ }
@@ -0,0 +1,5 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface Klaritics : NSObject <RCTBridgeModule>
4
+
5
+ @end
@@ -0,0 +1,176 @@
1
+ #import "Klaritics.h"
2
+ #import <AnthraSDK/AnthraSDK.h>
3
+ #import <AnthraSDK/ANTController.h>
4
+
5
+ @implementation Klaritics
6
+
7
+ RCT_EXPORT_MODULE(Klaritics)
8
+
9
+ - (instancetype)init {
10
+ self = [super init];
11
+ if (self) {
12
+ NSLog(@"Marking as React Native");
13
+ [[ANTController sharedController] markAsReactNative];
14
+ }
15
+ return self;
16
+ }
17
+
18
+ // this method was added to remove the warn when 'init' method is overridden
19
+ + (BOOL)requiresMainQueueSetup {
20
+ return YES;
21
+ }
22
+
23
+ + (BOOL)isInvalidString:(NSString*)aString {
24
+ if (nil == aString || [aString isEqualToString:@""]) {
25
+ return YES;
26
+ }
27
+ return NO;
28
+ }
29
+
30
+ + (NSDictionary *)validDictionary:(NSDictionary *)aDict {
31
+ if (nil == aDict) return nil;
32
+ if (![aDict isKindOfClass:[NSDictionary class]]) {
33
+ return nil;
34
+ }
35
+ NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
36
+ [aDict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
37
+ if ([(NSString *)key hasPrefix:@"@"]) {
38
+ NSCharacterSet *atRateCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"@"];
39
+ NSString *newKey = [(NSString *)key stringByTrimmingCharactersInSet:atRateCharacterSet];
40
+ [mutableDict setValue:obj forKey:newKey];
41
+ } else {
42
+ [mutableDict setValue:obj forKey:key];
43
+ }
44
+ }];
45
+
46
+ return [NSDictionary dictionaryWithDictionary:mutableDict];
47
+ }
48
+
49
+ RCT_EXPORT_METHOD(setUserIdentifier:(NSString *)identifier) {
50
+ if ([Klaritics isInvalidString:identifier]) {
51
+ NSLog(@"identifier cannot be empty or null");
52
+ return;
53
+ }
54
+ NSLog(@"setUserIdentifier API!");
55
+ [AnthraSDK setUserIdentifier:identifier];
56
+ }
57
+
58
+ RCT_EXPORT_METHOD(logNavigationEvent:(NSString *)title) {
59
+ if ([Klaritics isInvalidString:title]) {
60
+ NSLog(@"title cannot be empty or null");
61
+ return;
62
+ }
63
+ NSLog(@"logNavigationEvent API!");
64
+ [AnthraSDK logScreenWithName:title];
65
+ }
66
+
67
+ RCT_EXPORT_METHOD(setUserCustomInfo:(NSDictionary *)userCustomInfo) {
68
+ if (nil == userCustomInfo) {
69
+ NSLog(@"userCustomInfo cannot be null");
70
+ return;
71
+ }
72
+ NSLog(@"setUserCustomInfo API!");
73
+ [AnthraSDK setUserCustomInfo:[Klaritics validDictionary:userCustomInfo]];
74
+ }
75
+
76
+ RCT_EXPORT_METHOD(setSessionCustomInfo:(NSDictionary *)sessionCustomInfo) {
77
+ if (nil == sessionCustomInfo) {
78
+ NSLog(@"sessionCustomInfo cannot be null");
79
+ return;
80
+ }
81
+ NSLog(@"setSessionCustomInfo API!");
82
+ [AnthraSDK setSessionCustomInfo:[Klaritics validDictionary:sessionCustomInfo]];
83
+ }
84
+
85
+ RCT_REMAP_METHOD(logClientEvent,
86
+ logClientEventWithName:(NSString *)eventName
87
+ info:(NSDictionary *)info)
88
+ {
89
+ if ([Klaritics isInvalidString:eventName]) {
90
+ NSLog(@"eventName cannot be empty or null");
91
+ return;
92
+ }
93
+ NSLog(@"logClientEventWithName API !");
94
+ [AnthraSDK logClientEventWithName:eventName info:[Klaritics validDictionary:info]];
95
+ }
96
+
97
+ RCT_REMAP_METHOD(logAppEvent,
98
+ logAppEventWithName:(NSString *)eventName
99
+ info:(NSDictionary *)info
100
+ isAggregate:(BOOL)isAggregate) {
101
+ if ([Klaritics isInvalidString:eventName]) {
102
+ NSLog(@"eventName cannot be empty or null");
103
+ return;
104
+ }
105
+ NSLog(@"logAppEventWithName API!");
106
+ [AnthraSDK logAppEventWithName:eventName info:[Klaritics validDictionary:info] isAggregate:NO];
107
+ }
108
+
109
+ RCT_REMAP_METHOD(logAggregateEvent,
110
+ logAggregateEventWithName:(NSString *)eventName
111
+ info:(NSDictionary *)info) {
112
+ if ([Klaritics isInvalidString:eventName]) {
113
+ NSLog(@"eventName cannot be empty or null");
114
+ return;
115
+ }
116
+
117
+ NSLog(@"logAggregateEvent API!");
118
+ [[ANTController sharedController] logAppEventWithName:eventName info:[Klaritics validDictionary:info] isAggregate:YES];
119
+ }
120
+
121
+ RCT_REMAP_METHOD(logMetaEvent,
122
+ logMetaEventWithCategory:(NSString *)category event:(NSString *)event info:(NSDictionary *)info) {
123
+ if ([Klaritics isInvalidString:event]) {
124
+ NSLog(@"event cannot be empty or null");
125
+ return;
126
+ }
127
+ NSLog(@"logMetaEvent stub called!");
128
+ }
129
+
130
+ RCT_REMAP_METHOD(handlePushNotification,
131
+ handlePushNotificationWithInfo:(NSDictionary *)info) {
132
+ if (nil == info) {
133
+ NSLog(@"screen cannot be empty or null");
134
+ return;
135
+ }
136
+ NSLog(@"handlePushNotification stub called!");
137
+ }
138
+
139
+ RCT_REMAP_METHOD(trackScreen,
140
+ trackScreen:(NSString *)screen) {
141
+ if ([Klaritics isInvalidString:screen]) {
142
+ NSLog(@"screen cannot be empty or null");
143
+ return;
144
+ }
145
+ NSLog(@"trackScreen API!");
146
+ [AnthraSDK logScreenWithName:screen];
147
+ }
148
+
149
+ RCT_REMAP_METHOD(registerSimpleNotification,
150
+ registerSimpleNotification:(NSString *)notification :(NSString *)key) {
151
+ if ([Klaritics isInvalidString:notification] || [Klaritics isInvalidString:key]) {
152
+ NSLog(@"key or notification cannot be empty or null");
153
+ return;
154
+ }
155
+ NSLog(@"registerSimpleNotification stub called!");
156
+ }
157
+
158
+ RCT_REMAP_METHOD(unregisterSimpleNotification,
159
+ unregisterSimpleNotification:(NSString *)notification :(NSString *)key) {
160
+ if ([Klaritics isInvalidString:notification] || [Klaritics isInvalidString:key]) {
161
+ NSLog(@"key or notification cannot be empty or null");
162
+ return;
163
+ }
164
+ NSLog(@"unregisterSimpleNotification stub called!");
165
+ }
166
+
167
+ RCT_REMAP_METHOD(setApxorDynamicConfig,
168
+ setApxorDynamicConfig:(NSString *)key :(NSString *)value) {
169
+ if ([Klaritics isInvalidString:key] || [Klaritics isInvalidString:value]) {
170
+ NSLog(@"key or value cannot be empty or null");
171
+ return;
172
+ }
173
+ NSLog(@"setApxorDynamicConfig stub called!");
174
+ }
175
+
176
+ @end