react-native-mapp-plugin 1.3.6 → 1.4.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +19 -10
  2. package/Mapp.js +27 -4
  3. package/MappEventEmitter.js +4 -1
  4. package/RNMappPlugin.podspec +3 -4
  5. package/android/build.gradle +40 -20
  6. package/android/gradle/gradle-daemon-jvm.properties +12 -0
  7. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  8. package/android/gradle.properties +0 -2
  9. package/android/gradlew +18 -0
  10. package/android/gradlew.bat +15 -0
  11. package/android/settings.gradle +2 -4
  12. package/android/src/main/java/com/reactlibrary/ActivityListener.java +2 -4
  13. package/android/src/main/java/com/reactlibrary/HelperActivity.java +2 -2
  14. package/android/src/main/java/com/reactlibrary/MessageService.java +15 -10
  15. package/android/src/main/java/com/reactlibrary/MyPushBroadcastReceiver.java +29 -22
  16. package/android/src/main/java/com/reactlibrary/NativeRNMappPluginModuleSpec.java +232 -0
  17. package/android/src/main/java/com/reactlibrary/PushNotificationEvent.java +3 -3
  18. package/android/src/main/java/com/reactlibrary/RNMappPluginModule.java +525 -402
  19. package/android/src/main/java/com/reactlibrary/RNMappPluginPackage.java +9 -14
  20. package/android/src/main/java/com/reactlibrary/RNUtils.java +16 -16
  21. package/android/src/main/jni/CMakeLists.txt +28 -0
  22. package/android/src/main/jni/RNMappPlugin-generated.cpp +320 -0
  23. package/android/src/main/jni/RNMappPlugin.h +31 -0
  24. package/android/src/main/jni/react/renderer/components/RNMappPlugin/RNMappPluginJSI.h +471 -0
  25. package/ios/Frameworks/AppoxeeInapp.xcframework/Info.plist +5 -5
  26. package/ios/Frameworks/AppoxeeInapp.xcframework/ios-arm64/libAppoxeeInapp.a +0 -0
  27. package/ios/Frameworks/AppoxeeInapp.xcframework/ios-arm64_x86_64-simulator/libAppoxeeInapp.a +0 -0
  28. package/ios/Frameworks/AppoxeeSDK.xcframework/ios-arm64/libAppoxeeSDK.a +0 -0
  29. package/ios/Frameworks/AppoxeeSDK.xcframework/ios-arm64_x86_64-simulator/libAppoxeeSDK.a +0 -0
  30. package/package.json +65 -12
  31. package/react-native.config.js +6 -3
  32. package/specs/NativeRNMappPluginModule.js +59 -0
  33. package/.gitattributes +0 -1
  34. package/.local-pack/settings.json +0 -1
  35. package/.vscode/settings.json +0 -4
  36. package/Helper.md +0 -23
  37. package/__package.json +0 -33
  38. package/android/.classpath +0 -6
  39. package/android/.project +0 -34
  40. package/android/.settings/org.eclipse.buildship.core.prefs +0 -13
  41. package/clean.sh +0 -34
  42. package/ios/RNMappPlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  43. package/ios/RNMappPlugin.xcodeproj/project.xcworkspace/xcuserdata/stefan.stevanovic.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  44. package/ios/RNMappPlugin.xcodeproj/xcuserdata/stefan.stevanovic.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  45. package/jsdoc.conf.json +0 -15
  46. package/react-native-mapp-plugin-1.3.8.tgz +0 -0
  47. package/specs/MappEngagePluginSpec.js +0 -8
@@ -2,10 +2,19 @@
2
2
  package com.reactlibrary;
3
3
 
4
4
  import android.Manifest;
5
+ import android.app.Activity;
6
+ import android.app.AlertDialog;
5
7
  import android.app.Application;
6
- import android.content.pm.ActivityInfo;
8
+ import android.content.ActivityNotFoundException;
9
+ import android.content.DialogInterface;
10
+ import android.content.Intent;
7
11
  import android.content.pm.PackageManager;
12
+ import android.net.Uri;
8
13
  import android.os.Build;
14
+ import android.os.Handler;
15
+ import android.os.Looper;
16
+ import android.util.DisplayMetrics;
17
+ import android.provider.Settings;
9
18
 
10
19
  import androidx.annotation.NonNull;
11
20
  import androidx.annotation.Nullable;
@@ -13,30 +22,18 @@ import androidx.core.app.NotificationManagerCompat;
13
22
  import androidx.core.content.ContextCompat;
14
23
 
15
24
  import com.appoxee.Appoxee;
16
- import com.appoxee.AppoxeeOptions;
17
- import com.appoxee.DeviceInfo;
18
- import com.appoxee.GetCustomAttributesCallback;
19
- import com.appoxee.internal.inapp.model.APXInboxMessage;
20
- import com.appoxee.internal.inapp.model.ApxInAppExtras;
21
- import com.appoxee.internal.inapp.model.InAppInboxCallback;
22
- import com.appoxee.internal.inapp.model.InAppStatistics;
23
- import com.appoxee.internal.inapp.model.MessageContext;
24
- import com.appoxee.internal.inapp.model.Tracking;
25
- import com.appoxee.internal.inapp.model.TrackingAttributes;
26
- import com.appoxee.internal.permission.PermissionHelper;
27
- import com.appoxee.internal.permission.PermissionsCallback;
28
- import com.appoxee.internal.permission.PermissionsManager;
29
- import com.appoxee.internal.service.AppoxeeServiceAdapter;
30
- import com.appoxee.internal.util.ResultCallback;
31
- import com.appoxee.push.NotificationMode;
32
- import com.appoxee.push.PushData;
33
- import com.facebook.react.ReactActivity;
25
+ import com.appoxee.internal.model.response.DevicePayload;
26
+ import com.appoxee.shared.InboxMessage;
27
+ import com.appoxee.sdk.BuildConfig;
28
+ import com.appoxee.shared.AppoxeeObserver;
29
+ import com.appoxee.shared.AppoxeeOptions;
30
+ import com.appoxee.shared.MappResult;
31
+ import com.appoxee.shared.NotificationMode;
34
32
  import com.facebook.react.bridge.Arguments;
35
33
  import com.facebook.react.bridge.Callback;
36
34
  import com.facebook.react.bridge.LifecycleEventListener;
37
35
  import com.facebook.react.bridge.Promise;
38
36
  import com.facebook.react.bridge.ReactApplicationContext;
39
- import com.facebook.react.bridge.ReactContextBaseJavaModule;
40
37
  import com.facebook.react.bridge.ReactMethod;
41
38
  import com.facebook.react.bridge.ReadableArray;
42
39
  import com.facebook.react.bridge.ReadableMap;
@@ -44,6 +41,8 @@ import com.facebook.react.bridge.WritableArray;
44
41
  import com.facebook.react.bridge.WritableMap;
45
42
  import com.facebook.react.bridge.WritableNativeMap;
46
43
  import com.facebook.react.module.annotations.ReactModule;
44
+ import com.facebook.react.modules.core.PermissionAwareActivity;
45
+ import com.facebook.react.modules.core.PermissionListener;
47
46
  import com.google.android.gms.tasks.OnCompleteListener;
48
47
  import com.google.android.gms.tasks.Task;
49
48
  import com.google.firebase.messaging.FirebaseMessaging;
@@ -56,25 +55,37 @@ import java.util.ArrayList;
56
55
  import java.util.Collections;
57
56
  import java.util.Date;
58
57
  import java.util.HashMap;
58
+ import java.util.HashSet;
59
59
  import java.util.Iterator;
60
60
  import java.util.List;
61
+ import java.util.Locale;
61
62
  import java.util.Map;
62
63
  import java.util.Objects;
64
+ import java.util.TimeZone;
63
65
  import java.util.concurrent.ConcurrentHashMap;
64
66
 
65
67
  /**
66
68
  * Created by Aleksandar Marinkovic on 2019-05-15.
67
69
  * Copyright (c) 2019 MAPP.
70
+ * <p>
71
+ * Updated for Engage SDK v7:
72
+ * - All async operations use Call<T>.enqueue(MappCallback) instead of listener interfaces.
73
+ * - Push broadcast base class changed to LocalPushBroadcast via setPushBroadcast().
74
+ * - Ready/init observation changed to subscribe(AppoxeeObserver).
75
+ * - InApp statistics methods stubbed (v6 internal classes removed in v7).
68
76
  */
69
77
  @SuppressWarnings("ALL")
70
78
  @ReactModule(name = RNMappPluginModule.NAME)
71
- public class RNMappPluginModule extends ReactContextBaseJavaModule {
79
+ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements PermissionListener {
72
80
 
73
81
  public static final String NAME = "RNMappPluginModule";
82
+ private static final int POST_NOTIFICATION_PERMISSION_REQUEST_CODE = 1001;
74
83
  private final ReactApplicationContext reactContext;
75
84
  private Map<Callback, String> mFeedSubscriberMap = new ConcurrentHashMap<>();
76
85
  private Map<Callback, Boolean> mCallbackWasCalledMap = new ConcurrentHashMap<>();
86
+ private final Map<Integer, Promise> notificationPermissionPromises = new ConcurrentHashMap<>();
77
87
  private Application application = null;
88
+ private int nextNotificationPermissionRequestCode = POST_NOTIFICATION_PERMISSION_REQUEST_CODE;
78
89
 
79
90
  public RNMappPluginModule(ReactApplicationContext reactContext) {
80
91
  super(reactContext);
@@ -93,89 +104,155 @@ public class RNMappPluginModule extends ReactContextBaseJavaModule {
93
104
  getReactApplicationContext().addLifecycleEventListener(new LifecycleEventListener() {
94
105
  @Override
95
106
  public void onHostResume() {
96
- // Commented out for now.
97
- // It prevents the app from channging registered channel with a new one.
98
- // Appoxee.engage(application);
99
- // Appoxee.setOrientation(application, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
100
- // Appoxee.instance().setReceiver(MyPushBroadcastReceiver.class);
101
107
  }
102
108
 
103
109
  @Override
104
110
  public void onHostPause() {
105
-
106
111
  }
107
112
 
108
113
  @Override
109
114
  public void onHostDestroy() {
110
-
111
115
  }
112
-
113
116
  });
114
117
 
115
118
  EventEmitter.shared().attachReactContext(getReactApplicationContext());
116
119
  }
117
120
 
118
- private void reportResultWithCallback(Callback callback, String error, Object result) {
119
- if (callback != null) {
120
- if (error != null) {
121
- callback.invoke(error);
122
- } else {
123
- callback.invoke(null, result);
124
- }
125
- }
126
- }
121
+ // -------------------------------------------------------------------------
122
+ // Permissions
123
+ // -------------------------------------------------------------------------
127
124
 
128
125
  @ReactMethod
129
126
  public void requestGeofenceLocationPermission(Promise promise) {
130
127
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
131
128
  promise.resolve(true);
132
- } else {
133
- if (getCurrentActivity() instanceof ReactActivity) {
134
- int fineLocation = getCurrentActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
135
- int backgroundLocation = getCurrentActivity().checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
136
-
137
- if (fineLocation != PermissionsManager.PERMISSION_GRANTED ||
138
- backgroundLocation != PermissionsManager.PERMISSION_GRANTED) {
139
- PermissionHelper.getInstance().openAppSystemSettings(getCurrentActivity());
140
- promise.resolve(false);
141
- } else {
142
- promise.resolve(true);
143
- }
144
- } else {
145
- promise.reject("Can't access activity for requesting permission!");
146
- }
129
+ return;
147
130
  }
131
+ int fineLocation = ContextCompat.checkSelfPermission(reactContext, Manifest.permission.ACCESS_FINE_LOCATION);
132
+ int backgroundLocation = ContextCompat.checkSelfPermission(reactContext, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
133
+ promise.resolve(fineLocation == PackageManager.PERMISSION_GRANTED
134
+ && backgroundLocation == PackageManager.PERMISSION_GRANTED);
148
135
  }
149
136
 
150
137
  @ReactMethod
151
138
  public void requestPostNotificationPermission(Promise promise) {
152
139
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
153
140
  promise.resolve(true);
154
- } else {
155
- if (getCurrentActivity() instanceof ReactActivity) {
156
- ReactActivity activity = (ReactActivity) getCurrentActivity();
157
- Appoxee.instance().requestNotificationsPermission(activity, new PermissionsCallback() {
158
- @Override
159
- public void onPermissionsResult(Map<String, Integer> map) {
160
- if (map.containsKey(Manifest.permission.POST_NOTIFICATIONS)) {
161
- Integer result = map.get(Manifest.permission.POST_NOTIFICATIONS);
162
- promise.resolve(result == PermissionsManager.PERMISSION_GRANTED);
163
- } else {
164
- promise.resolve(false);
165
- }
166
- }
167
- });
168
- } else {
169
- promise.reject("Can't access activity for requesting permission!");
141
+ return;
142
+ }
143
+ int result = ContextCompat.checkSelfPermission(reactContext, Manifest.permission.POST_NOTIFICATIONS);
144
+ if (result == PackageManager.PERMISSION_GRANTED) {
145
+ promise.resolve(true);
146
+ return;
147
+ }
148
+
149
+ Activity activity = getCurrentActivity();
150
+ if (!(activity instanceof PermissionAwareActivity)) {
151
+ showNotificationSettingsPrompt(activity, promise);
152
+ return;
153
+ }
154
+
155
+ int requestCode = nextNotificationPermissionRequestCode++;
156
+ notificationPermissionPromises.put(requestCode, promise);
157
+ try {
158
+ ((PermissionAwareActivity) activity).requestPermissions(
159
+ new String[]{Manifest.permission.POST_NOTIFICATIONS},
160
+ requestCode,
161
+ this
162
+ );
163
+ } catch (IllegalStateException e) {
164
+ notificationPermissionPromises.remove(requestCode);
165
+ showNotificationSettingsPrompt(activity, promise);
166
+ }
167
+ }
168
+
169
+ @Override
170
+ public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
171
+ Promise promise = notificationPermissionPromises.remove(requestCode);
172
+ if (promise == null) {
173
+ return false;
174
+ }
175
+
176
+ boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
177
+ if (granted) {
178
+ promise.resolve(true);
179
+ return true;
180
+ }
181
+
182
+ Activity activity = getCurrentActivity();
183
+ if (activity instanceof PermissionAwareActivity
184
+ && !((PermissionAwareActivity) activity).shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
185
+ showNotificationSettingsPrompt(activity, promise);
186
+ return true;
187
+ }
188
+
189
+ promise.resolve(false);
190
+ return true;
191
+ }
192
+
193
+ private void showNotificationSettingsPrompt(@Nullable Activity activity, Promise promise) {
194
+ if (activity == null) {
195
+ resolveWithNotificationSettingsFallback(promise);
196
+ return;
197
+ }
198
+
199
+ activity.runOnUiThread(() -> {
200
+ try {
201
+ new AlertDialog.Builder(activity)
202
+ .setTitle("Notifications disabled")
203
+ .setMessage("Notification permission is required. Open app settings to enable it manually.")
204
+ .setCancelable(true)
205
+ .setPositiveButton("Open settings", (DialogInterface dialog, int which) -> {
206
+ resolveWithNotificationSettingsFallback(promise);
207
+ })
208
+ .setNegativeButton("Cancel", (DialogInterface dialog, int which) -> promise.resolve(false))
209
+ .show();
210
+ } catch (RuntimeException e) {
211
+ resolveWithNotificationSettingsFallback(promise);
170
212
  }
213
+ });
214
+ }
215
+
216
+ private void openNotificationSettings() {
217
+ Intent intent;
218
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
219
+ intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
220
+ intent.putExtra(Settings.EXTRA_APP_PACKAGE, reactContext.getPackageName());
221
+ } else {
222
+ intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
223
+ intent.setData(Uri.fromParts("package", reactContext.getPackageName(), null));
224
+ }
225
+
226
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
227
+ try {
228
+ reactContext.startActivity(intent);
229
+ } catch (ActivityNotFoundException e) {
230
+ Intent fallbackIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
231
+ fallbackIntent.setData(Uri.fromParts("package", reactContext.getPackageName(), null));
232
+ fallbackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
233
+ reactContext.startActivity(fallbackIntent);
171
234
  }
172
235
  }
173
236
 
237
+ private void resolveWithNotificationSettingsFallback(Promise promise) {
238
+ try {
239
+ openNotificationSettings();
240
+ } catch (RuntimeException e) {
241
+ // Best effort only: the caller still gets a definitive outcome.
242
+ } finally {
243
+ promise.resolve(false);
244
+ }
245
+ }
246
+
247
+ // -------------------------------------------------------------------------
248
+ // Remote message
249
+ // -------------------------------------------------------------------------
250
+
174
251
  @ReactMethod
175
252
  public void setRemoteMessage(String msgJson, Promise promise) {
176
253
  RemoteMessage remoteMessage = getRemoteMessage(msgJson);
177
254
  if (remoteMessage != null) {
178
- Appoxee.instance().setRemoteMessage(remoteMessage);
255
+ Appoxee.instance().handlePushMessage(remoteMessage);
179
256
  promise.resolve(true);
180
257
  } else {
181
258
  promise.resolve(false);
@@ -184,19 +261,25 @@ public class RNMappPluginModule extends ReactContextBaseJavaModule {
184
261
 
185
262
  @ReactMethod
186
263
  public void isPushFromMapp(String msgJson, Promise promise) {
264
+ promise.resolve(isMappPush(msgJson));
265
+ }
266
+
267
+ static boolean isMappPush(@Nullable String msgJson) {
187
268
  try {
188
269
  JSONObject json = new JSONObject(msgJson);
189
- boolean mappPush = json.has("data") && json.getJSONObject("data").has("p");
190
- promise.resolve(mappPush);
270
+ return json.has("data") && json.getJSONObject("data").has("p");
191
271
  } catch (Exception e) {
192
- promise.resolve(false);
272
+ return false;
193
273
  }
194
274
  }
195
275
 
276
+ // -------------------------------------------------------------------------
277
+ // Token
278
+ // -------------------------------------------------------------------------
279
+
196
280
  @ReactMethod
197
281
  public void setToken(String token, Promise promise) {
198
- Appoxee.instance().setToken(token);
199
- promise.resolve(true);
282
+ Appoxee.instance().updateFirebaseToken(token).enqueue(result -> promise.resolve(true));
200
283
  }
201
284
 
202
285
  @ReactMethod
@@ -204,355 +287,495 @@ public class RNMappPluginModule extends ReactContextBaseJavaModule {
204
287
  FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
205
288
  @Override
206
289
  public void onComplete(@NonNull Task<String> task) {
207
- String token = task.getResult();
208
- promise.resolve(token);
290
+ promise.resolve(task.getResult());
209
291
  }
210
292
  });
211
293
  }
212
294
 
295
+ // -------------------------------------------------------------------------
296
+ // Alias
297
+ // -------------------------------------------------------------------------
298
+
213
299
  @ReactMethod
214
300
  public void setAlias(String alias, Promise promise) {
215
- Appoxee.instance().setAlias(alias, false);
216
- promise.resolve(true);
301
+ Appoxee.instance().setAlias(alias, false).enqueue(result -> promise.resolve(true));
217
302
  }
218
303
 
219
304
  @ReactMethod
220
305
  public void setAliasWithResend(String alias, boolean resendCustomAttributes, Promise promise) {
221
- Appoxee.instance().setAlias(alias, resendCustomAttributes);
222
- promise.resolve(true);
306
+ Appoxee.instance().setAlias(alias, resendCustomAttributes).enqueue(result -> promise.resolve(true));
223
307
  }
224
308
 
225
309
  @ReactMethod
310
+ public void getAlias(Promise promise) {
311
+ Appoxee.instance().getAlias().enqueue(result -> promise.resolve(result.getData()));
312
+ }
313
+
314
+ // -------------------------------------------------------------------------
315
+ // Engage / init
316
+ // -------------------------------------------------------------------------
317
+
318
+ @ReactMethod
319
+ @Deprecated(forRemoval = true)
226
320
  public void engage2() {
227
- Appoxee.engage(Objects.requireNonNull(application));
321
+ Appoxee.engage(application,null);
228
322
  }
229
323
 
230
324
  @ReactMethod
231
325
  public void engage(String sdkKey, String googleProjectId, String server, String appID, String tenantID) {
232
- AppoxeeOptions opt = new AppoxeeOptions();
233
- opt.appID = appID;
234
- opt.sdkKey = sdkKey;
235
- opt.server = AppoxeeOptions.Server.valueOf(server);
236
- if (server.equals("TEST") || server.equals("TEST55") || server.equals("TEST_55")) {
237
- opt.cepURL = "https://jamie-test.shortest-route.com";
238
- }
239
- opt.notificationMode = NotificationMode.BACKGROUND_AND_FOREGROUND;
240
- opt.tenantID = tenantID;
241
- Appoxee.engage(Objects.requireNonNull(application), opt);
326
+ AppoxeeOptions opt = createOptions(server, sdkKey, appID, tenantID);
327
+ opt.setNotificationMode(NotificationMode.BACKGROUND_AND_FOREGROUND);
242
328
 
243
- Appoxee.instance().addInitListener(new Appoxee.OnInitCompletedListener() {
244
- @Override
245
- public void onInitCompleted(boolean successful, Exception failReason) {
246
- /**
247
- * OnInitCompleteListener must be attached;
248
- * Internally {@link AppoxeeServiceAdapter#getDeviceInfoDMC()} is called and
249
- * "user_id" created.
250
- * If "user_id" is null InApp messages are not working.
251
- */
252
- }
329
+ new Handler(Looper.getMainLooper()).post(() -> {
330
+ Appoxee.engage(Objects.requireNonNull(application), opt);
331
+
332
+ Appoxee.instance().subscribe(new AppoxeeObserver() {
333
+ @Override
334
+ public void onReadyStatusChanged(boolean status, MappResult<DevicePayload> result) {
335
+ }
336
+ });
337
+
338
+ Appoxee.instance().setPushBroadcast(MyPushBroadcastReceiver.class);
253
339
  });
254
- Appoxee.setOrientation(application, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
255
- Appoxee.instance().setReceiver(MyPushBroadcastReceiver.class);
256
340
  }
257
341
 
258
342
  @ReactMethod
259
- public void engageTestServer(String cepURl, String sdkKey, String googleProjectId, String server, String appID,
260
- String tenantID) {
261
- AppoxeeOptions opt = new AppoxeeOptions();
262
- opt.appID = appID;
263
- opt.sdkKey = sdkKey;
264
- opt.server = AppoxeeOptions.Server.valueOf(server);
265
- opt.cepURL = cepURl;
266
- opt.tenantID = tenantID;
267
- Appoxee.setOrientation(application, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
343
+ public void engageTestServer(String cepURl, String sdkKey, String googleProjectId, String server,
344
+ String appID, String tenantID) {
345
+ AppoxeeOptions opt = createOptions(server, sdkKey, appID, tenantID);
268
346
 
269
- Appoxee.engage(Objects.requireNonNull(application), opt);
347
+ new Handler(Looper.getMainLooper()).post(() -> {
348
+ Appoxee.engage(Objects.requireNonNull(application), opt);
349
+
350
+ Appoxee.instance().subscribe(new AppoxeeObserver() {
351
+ @Override
352
+ public void onReadyStatusChanged(boolean status, MappResult<DevicePayload> result) {
353
+ }
354
+ });
355
+
356
+ Appoxee.instance().setPushBroadcast(MyPushBroadcastReceiver.class);
357
+ });
270
358
  }
271
359
 
272
- @ReactMethod
273
- public void setPushEnabled(boolean optIn) {
274
- Appoxee.instance().setPushEnabled(optIn);
360
+ static AppoxeeOptions createOptions(String server, String sdkKey, String appID, String tenantID) {
361
+ AppoxeeOptions.Server resolvedServer = resolveServer(server);
362
+ if (resolvedServer == null) {
363
+ throw new IllegalArgumentException(
364
+ "Unsupported Mapp server '" + server
365
+ + "'. Use L3, L3_US, EMC, EMC_US, CROC, TEST, TEST55, TEST61, or a full server URL."
366
+ );
367
+ }
275
368
 
369
+ return new AppoxeeOptions(resolvedServer, sdkKey, appID, tenantID);
370
+ }
371
+
372
+ @Nullable
373
+ static AppoxeeOptions.Server resolveServer(@Nullable String server) {
374
+ if (server == null) {
375
+ return null;
376
+ }
377
+
378
+ String normalizedServer = server.trim();
379
+ if (normalizedServer.isEmpty()) {
380
+ return null;
381
+ }
382
+
383
+ switch (normalizedServer.toUpperCase(Locale.ROOT)) {
384
+ case "L3":
385
+ return AppoxeeOptions.Server.L3;
386
+ case "L3_US":
387
+ case "L3US":
388
+ return AppoxeeOptions.Server.L3_US;
389
+ case "EMC":
390
+ return AppoxeeOptions.Server.EMC;
391
+ case "EMC_US":
392
+ case "EMCUS":
393
+ return AppoxeeOptions.Server.EMC_US;
394
+ case "CROC":
395
+ return AppoxeeOptions.Server.CROC;
396
+ case "TEST":
397
+ return AppoxeeOptions.Server.TEST;
398
+ case "TEST55":
399
+ case "TEST_55":
400
+ return AppoxeeOptions.Server.TEST_55;
401
+ case "TEST61":
402
+ case "TEST_61":
403
+ return AppoxeeOptions.Server.TEST_61;
404
+ default:
405
+ return AppoxeeOptions.Server.get(normalizedServer);
406
+ }
276
407
  }
277
408
 
278
409
  @ReactMethod
279
- public void isPushEnabled(Promise promise) {
280
- promise.resolve(Appoxee.instance().isPushEnabled());
410
+ public void onInitCompletedListener(final Promise promise) {
411
+ Appoxee.instance().subscribe(new AppoxeeObserver() {
412
+ @Override
413
+ public void onReadyStatusChanged(boolean status, MappResult<DevicePayload> result) {
414
+ promise.resolve(status);
415
+ }
416
+ });
281
417
  }
282
418
 
283
419
  @ReactMethod
284
420
  public void isReady(Promise promise) {
285
421
  promise.resolve(Appoxee.instance().isReady());
422
+ }
423
+
424
+ // -------------------------------------------------------------------------
425
+ // Push opt-in / opt-out
426
+ // -------------------------------------------------------------------------
286
427
 
428
+ @ReactMethod
429
+ public void setPushEnabled(boolean optIn) {
430
+ Appoxee.instance().enablePush(optIn, null).enqueue(result -> {
431
+ });
287
432
  }
288
433
 
289
434
  @ReactMethod
290
- public void onInitCompletedListener(final Promise promise) {
291
- Appoxee.instance().addInitListener(new Appoxee.OnInitCompletedListener() {
292
- @Override
293
- public void onInitCompleted(boolean b, Exception e) {
294
- promise.resolve(b);
295
- }
435
+ public void isPushEnabled(Promise promise) {
436
+ Appoxee.instance().isPushEnabled().enqueue(result -> {
437
+ Boolean enabled = (result != null && result.isSuccess()) ? result.getData() : false;
438
+ promise.resolve(enabled != null ? enabled : false);
296
439
  });
297
440
  }
298
441
 
442
+ // -------------------------------------------------------------------------
443
+ // Custom attributes (bulk)
444
+ // -------------------------------------------------------------------------
445
+
299
446
  @ReactMethod
300
447
  public void setAttributes(ReadableMap attributes, Promise promise) {
301
448
  if (attributes != null) {
302
- Map<String, Object> internapMap = new HashMap<>();
449
+ Map<String, Object> internalMap = new HashMap<>();
303
450
  attributes.getEntryIterator().forEachRemaining(entry -> {
304
451
  Object value = entry.getValue() == null ? "" : entry.getValue();
305
452
  String key = entry.getKey();
306
-
307
453
  if (value instanceof Number) {
308
- internapMap.put(key, ((Number) value).doubleValue());
454
+ internalMap.put(key, ((Number) value).doubleValue());
309
455
  } else if (value instanceof Boolean) {
310
- internapMap.put(key, ((Boolean) value).booleanValue());
456
+ internalMap.put(key, (Boolean) value);
311
457
  } else if (value instanceof Date) {
312
- internapMap.put(key, ((Date) value).getDate());
458
+ internalMap.put(key, ((Date) value).getDate());
313
459
  } else {
314
- internapMap.put(key, ((String) value));
460
+ internalMap.put(key, value.toString());
315
461
  }
316
462
  });
317
- Appoxee.instance().setAttributes(internapMap);
463
+ Appoxee.instance().addCustomAttributes(internalMap).enqueue(result -> promise.resolve(true));
464
+ } else {
465
+ promise.resolve(true);
318
466
  }
319
- promise.resolve(true);
320
467
  }
321
468
 
322
469
  @ReactMethod
323
470
  public void getAttributes(ReadableArray keys, Promise promise) {
324
471
  List<String> internalKeys = new ArrayList<>();
325
-
326
472
  if (keys != null && keys.size() > 0) {
327
473
  for (int i = 0; i < keys.size(); i++) {
328
474
  internalKeys.add(keys.getString(i));
329
475
  }
330
476
  }
331
477
 
332
- if (internalKeys.size() > 0) {
333
- Appoxee.instance().getCustomAttributes(internalKeys, new GetCustomAttributesCallback() {
334
- @Override
335
- public void onSuccess(Map<String, String> customAttributes) {
478
+ if (!internalKeys.isEmpty()) {
479
+ Appoxee.instance().getCustomAttributes(new HashSet<>(internalKeys)).enqueue(result -> {
480
+ if (result != null && result.isSuccess()) {
481
+ Map<String, Object> customAttributes = (Map<String, Object>) result.getData();
336
482
  WritableMap resultMap = new WritableNativeMap();
337
- for (Map.Entry<String, String> entry : customAttributes.entrySet()) {
338
- resultMap.putString(entry.getKey(), entry.getValue());
483
+ if (customAttributes != null) {
484
+ for (Map.Entry<String, Object> entry : customAttributes.entrySet()) {
485
+ resultMap.putString(entry.getKey(),
486
+ entry.getValue() != null ? entry.getValue().toString() : "");
487
+ }
339
488
  }
340
489
  promise.resolve(resultMap);
341
- }
342
-
343
- @Override
344
- public void onError(String errorMessage) {
345
- promise.reject(new Throwable(errorMessage));
490
+ } else {
491
+ Throwable error = (result != null && result.getError() != null) ? result.getError() : new Throwable("Error getting attributes");
492
+ promise.reject(error);
346
493
  }
347
494
  });
348
495
  } else {
349
- promise.resolve(Collections.emptyMap());
496
+ promise.resolve(new WritableNativeMap());
350
497
  }
351
498
  }
352
499
 
500
+ // -------------------------------------------------------------------------
501
+ // Custom attributes (single)
502
+ // -------------------------------------------------------------------------
503
+
353
504
  @ReactMethod
354
505
  public void setAttribute(String key, String value) {
355
- Appoxee.instance().setAttribute(key, value);
356
-
506
+ Map<String, Object> attr = new HashMap<>();
507
+ attr.put(key, value);
508
+ Appoxee.instance().addCustomAttributes(attr).enqueue(result -> {
509
+ });
357
510
  }
358
511
 
359
512
  @ReactMethod
360
- public void setAttributeBoolean(String key, Boolean value) {
361
- Appoxee.instance().setAttribute(key, value);
513
+ public void setAttributeBoolean(String key, boolean value) {
514
+ Map<String, Object> attr = new HashMap<>();
515
+ attr.put(key, value);
516
+ Appoxee.instance().addCustomAttributes(attr).enqueue(result -> {
517
+ });
518
+ }
362
519
 
520
+ @ReactMethod
521
+ public void setAttributeInt(String key, double value) {
522
+ Map<String, Object> attr = new HashMap<>();
523
+ attr.put(key, (int) value);
524
+ Appoxee.instance().addCustomAttributes(attr).enqueue(result -> {
525
+ });
363
526
  }
364
527
 
365
528
  @ReactMethod
366
- public void setAttributeInt(String key, Integer value) {
367
- Appoxee.instance().setAttribute(key, value);
529
+ public void removeAttribute(String attribute) {
530
+ Appoxee.instance().removeCustomAttributes(Collections.singleton(attribute)).enqueue(result -> {
531
+ });
532
+ }
368
533
 
534
+ @ReactMethod
535
+ public void getAttributeStringValue(String key, Promise promise) {
536
+ Appoxee.instance().getCustomAttributes(Collections.singleton(key)).enqueue(result -> {
537
+ if (result != null && result.isSuccess() && result.getData() != null) {
538
+ Map<String, Object> attrs = (Map<String, Object>) result.getData();
539
+ Object value = attrs.get(key);
540
+ promise.resolve(value != null ? value.toString() : null);
541
+ } else {
542
+ promise.resolve(null);
543
+ }
544
+ });
369
545
  }
370
546
 
547
+ // -------------------------------------------------------------------------
548
+ // Tags
549
+ // -------------------------------------------------------------------------
550
+
371
551
  @ReactMethod
372
552
  public void addTag(String tag) {
373
- Appoxee.instance().addTag(tag);
374
-
553
+ Appoxee.instance().addTags(Collections.singleton(tag)).enqueue(result -> {
554
+ });
375
555
  }
376
556
 
377
557
  @ReactMethod
378
558
  public void removeTag(String tag) {
379
- Appoxee.instance().removeTag(tag);
380
-
559
+ Appoxee.instance().removeTags(Collections.singleton(tag)).enqueue(result -> {
560
+ });
381
561
  }
382
562
 
383
563
  @ReactMethod
384
564
  public void getTags(Promise promise) {
385
-
386
- WritableArray array = Arguments.createArray();
387
- for (String tag : Appoxee.instance().getTags()) {
388
- array.pushString(tag);
389
- }
390
- promise.resolve(array);
565
+ Appoxee.instance().getTags().enqueue(result -> {
566
+ WritableArray array = Arguments.createArray();
567
+ if (result != null && result.isSuccess() && result.getData() != null) {
568
+ for (String tag : result.getData()) {
569
+ array.pushString(tag);
570
+ }
571
+ }
572
+ promise.resolve(array);
573
+ });
391
574
  }
392
575
 
393
- @ReactMethod
394
- public void removeAttribute(String attribute) {
395
- Appoxee.instance().removeAttribute(attribute);
396
- }
576
+ // -------------------------------------------------------------------------
577
+ // Device info
578
+ // -------------------------------------------------------------------------
397
579
 
398
580
  @ReactMethod
399
- public void getAlias(Promise promise) {
400
- promise.resolve(Appoxee.instance().getAlias());
581
+ public void getDeviceInfo(Promise promise) {
582
+ Appoxee.instance().getDevice().enqueue(result -> {
583
+ WritableMap deviceInfo = new WritableNativeMap();
584
+ try {
585
+ // Use dmcUserId from v7 DevicePayload as the device id
586
+ DevicePayload payload = (result != null && result.isSuccess()) ? result.getData() : null;
587
+ deviceInfo.putString("id", payload != null && payload.getDmcUserId() != null
588
+ ? payload.getDmcUserId() : "");
589
+
590
+ // Reconstruct app/device metadata from Android APIs (removed from v7 DevicePayload)
591
+ try {
592
+ String appVersion = reactContext.getPackageManager()
593
+ .getPackageInfo(reactContext.getPackageName(), 0).versionName;
594
+ deviceInfo.putString("appVersion", appVersion != null ? appVersion : "");
595
+ } catch (PackageManager.NameNotFoundException e) {
596
+ deviceInfo.putString("appVersion", "");
597
+ }
598
+ deviceInfo.putString("sdkVersion", BuildConfig.VERSION_NAME);
599
+ deviceInfo.putString("locale", Locale.getDefault().toString());
600
+ deviceInfo.putString("timezone", TimeZone.getDefault().getID());
601
+ deviceInfo.putString("deviceModel", Build.MODEL);
602
+ deviceInfo.putString("manufacturer", Build.MANUFACTURER);
603
+ deviceInfo.putString("osVersion", Build.VERSION.RELEASE);
604
+
605
+ DisplayMetrics dm = reactContext.getResources().getDisplayMetrics();
606
+ deviceInfo.putString("resolution", dm.widthPixels + "x" + dm.heightPixels);
607
+ deviceInfo.putString("density", String.valueOf(dm.density));
608
+ } catch (Exception e) {
609
+ e.printStackTrace();
610
+ }
611
+ promise.resolve(deviceInfo);
612
+ });
401
613
  }
402
614
 
403
615
  @ReactMethod
404
- public void getDeviceInfo(Promise promise) {
405
- promise.resolve(getDeviceInfoJson(Appoxee.instance().getDeviceInfo()));
616
+ public void getDeviceDmcInfo(final Promise promise) {
617
+ Appoxee.instance().getDevice().enqueue(result -> {
618
+ try {
619
+ DevicePayload payload = (result != null && result.isSuccess()) ? result.getData() : null;
620
+ WritableMap wm = new WritableNativeMap();
621
+ if (payload != null) {
622
+ if (payload.getDmcUserId() != null)
623
+ wm.putString("dmcUserId", payload.getDmcUserId());
624
+ if (payload.getUdidHashed() != null)
625
+ wm.putString("udidHashed", payload.getUdidHashed());
626
+ if (payload.getPushTokenBk() != null)
627
+ wm.putString("pushTokenBk", payload.getPushTokenBk());
628
+ if (payload.getPushToken() != null)
629
+ wm.putString("pushToken", payload.getPushToken());
630
+ if (payload.getAlias() != null) wm.putString("alias", payload.getAlias());
631
+ }
632
+ promise.resolve(wm);
633
+ } catch (Exception e) {
634
+ promise.reject("Error getting DMC Info", e);
635
+ }
636
+ });
406
637
  }
407
638
 
408
639
  @ReactMethod
409
- public void getAttributeStringValue(String value, Promise promise) {
410
- promise.resolve(Appoxee.instance().getAttributeStringValue(value));
640
+ public void isDeviceRegistered(Promise promise) {
641
+ // isDeviceRegistered() removed in v7; derive from DevicePayload presence
642
+ Appoxee.instance().getDevice().enqueue(result -> {
643
+ boolean registered = result != null && result.isSuccess()
644
+ && result.getData() != null
645
+ && result.getData().getDmcUserId() != null;
646
+ promise.resolve(registered);
647
+ });
411
648
  }
412
649
 
650
+ // -------------------------------------------------------------------------
651
+ // Screen / badge
652
+ // -------------------------------------------------------------------------
653
+
413
654
  @ReactMethod
414
- public void lockScreenOrientation(Integer orientation) {
415
- Appoxee.setOrientation(Objects.requireNonNull((Application) reactContext.getApplicationContext()), orientation);
655
+ public void lockScreenOrientation(double orientation) {
656
+ // setOrientation() removed in SDK v7 — no-op
416
657
  }
417
658
 
418
659
  @ReactMethod
419
660
  public void removeBadgeNumber() {
420
- Appoxee.removeBadgeNumber(Objects.requireNonNull((Application) reactContext.getApplicationContext()));
661
+ // removeBadgeNumber() removed in SDK v7 — no-op
421
662
  }
422
663
 
664
+ // -------------------------------------------------------------------------
665
+ // Geofencing
666
+ // -------------------------------------------------------------------------
667
+
423
668
  @ReactMethod
424
669
  public void startGeofencing(final Promise promise) {
425
- Appoxee.instance().startGeoFencing(new ResultCallback<String>() {
426
- @Override
427
- public void onResult(@Nullable String result) {
428
- promise.resolve(result);
670
+ Appoxee.instance().startGeofencing(0).enqueue(result -> {
671
+ if (result != null && result.isSuccess() && result.getData() != null) {
672
+ promise.resolve(result.getData().getStatus());
673
+ } else {
674
+ promise.resolve("GEOFENCE_GENERAL_ERROR");
429
675
  }
430
676
  });
431
677
  }
432
678
 
433
679
  @ReactMethod
434
680
  public void stopGeofencing(final Promise promise) {
435
- Appoxee.instance().stopGeoFencing(new ResultCallback<String>() {
436
- @Override
437
- public void onResult(@Nullable String result) {
438
- promise.resolve(result);
681
+ Appoxee.instance().stopGeofencing().enqueue(result -> {
682
+ if (result != null && result.isSuccess() && result.getData() != null) {
683
+ promise.resolve(result.getData().getStatus());
684
+ } else {
685
+ promise.resolve("GEOFENCE_GENERAL_ERROR");
439
686
  }
440
687
  });
441
688
  }
442
689
 
443
- /**
444
- * This method is deprecated in Java. Use method
445
- * {@link #startGeofencing(ResultCallback)}}
446
- */
690
+ @Deprecated
447
691
  @ReactMethod
448
- @Deprecated()
449
692
  public void startGeoFencing() {
450
- Appoxee.instance().startGeoFencing();
693
+ Appoxee.instance().startGeofencing(0).enqueue(result -> {
694
+ });
451
695
  }
452
696
 
453
- /**
454
- * Deprecated in Java. Use method {@link #stopGeofencing(ResultCallback)}
455
- */
456
697
  @Deprecated
457
698
  @ReactMethod
458
699
  public void stopGeoFencing() {
459
- Appoxee.instance().stopGeoFencing();
700
+ Appoxee.instance().stopGeofencing().enqueue(result -> {
701
+ });
460
702
  }
461
703
 
704
+ // -------------------------------------------------------------------------
705
+ // Inbox / InApp
706
+ // -------------------------------------------------------------------------
707
+
462
708
  @ReactMethod
463
709
  public void fetchLatestInboxMessage(final Promise promise) {
464
-
465
- Appoxee.instance().fetchInboxMessages();
466
-
467
- InAppInboxCallback inAppInboxCallback = new InAppInboxCallback();
468
- inAppInboxCallback.addInAppInboxMessagesReceivedCallback(new InAppInboxCallback.onInAppInboxMessagesReceived() {
469
- @Override
470
- public void onInAppInboxMessages(List<APXInboxMessage> richMessages) {
471
- WritableArray messagesArray = Arguments.createArray();
472
- APXInboxMessage msg = null;
473
- if (richMessages != null) {
474
- for (APXInboxMessage message : richMessages) {
475
- if (msg == null || message.getTemplateId() > msg.getTemplateId()) {
476
- msg = message;
477
- }
478
- messagesArray.pushMap(messageToJson(message));
479
- }
480
- }
481
- promise.resolve(msg != null ? messageToJson(msg) : null);
482
- }
483
-
484
- @Override
485
- public void onInAppInboxMessage(final APXInboxMessage message) {
486
- promise.resolve(messageToJson(message));
710
+ Appoxee.instance().fetchLatestInboxMessage().enqueue(result -> {
711
+ if (result != null && result.isSuccess()) {
712
+ promise.resolve(messageToJson(result.getData()));
713
+ } else {
714
+ promise.resolve(null);
487
715
  }
488
716
  });
489
717
  }
490
718
 
491
719
  @ReactMethod
492
720
  public void fetchInboxMessage(final Promise promise) {
493
-
494
- Appoxee.instance().fetchInboxMessages();
495
-
496
- InAppInboxCallback inAppInboxCallback = new InAppInboxCallback();
497
- inAppInboxCallback.addInAppInboxMessagesReceivedCallback(new InAppInboxCallback.onInAppInboxMessagesReceived() {
498
- @Override
499
- public void onInAppInboxMessages(List<APXInboxMessage> richMessages) {
500
- WritableArray messagesArray = Arguments.createArray();
501
- if (richMessages != null)
502
- for (APXInboxMessage message : richMessages) {
721
+ Appoxee.instance().fetchInboxMessages().enqueue(result -> {
722
+ WritableArray messagesArray = Arguments.createArray();
723
+ if (result != null && result.isSuccess() && result.getData() != null) {
724
+ List<InboxMessage> messages = result.getData().getMessages();
725
+ if (messages != null) {
726
+ for (InboxMessage message : messages) {
503
727
  messagesArray.pushMap(messageToJson(message));
504
728
  }
505
- promise.resolve(messagesArray);
506
- }
507
-
508
- @Override
509
- public void onInAppInboxMessage(final APXInboxMessage message) {
510
- promise.resolve(messageToJson(message));
729
+ }
511
730
  }
731
+ promise.resolve(messagesArray);
512
732
  });
513
733
  }
514
734
 
515
735
  @ReactMethod
516
736
  public void triggerInApp(String key) {
517
- Appoxee.instance().triggerInApp((getCurrentActivity()), key);
737
+ Appoxee.instance().triggerInApp(getCurrentActivity(), key).enqueue(result -> {
738
+ });
518
739
  }
519
740
 
741
+ /**
742
+ * Stubbed: InApp statistics internal classes were removed in v7.
743
+ * The @ReactMethod signature is preserved to avoid breaking the JS public API.
744
+ */
520
745
  @ReactMethod
521
- public void inAppMarkAsRead(Integer templateId, String eventId) {
522
- Appoxee.instance().triggerStatistcs((getCurrentActivity()), getInAppStatisticsRequestObject(templateId,
523
- eventId,
524
- InAppStatistics.INBOX_INBOX_MESSAGE_READ_KEY, -1, null, null));
746
+ public void inAppMarkAsRead(double templateId, String eventId) {
747
+ // no-op in v7
525
748
  }
526
749
 
750
+ /**
751
+ * @see #inAppMarkAsRead
752
+ */
527
753
  @ReactMethod
528
- public void inAppMarkAsUnRead(Integer templateId, String eventId) {
529
- Appoxee.instance().triggerStatistcs((reactContext.getApplicationContext()),
530
- getInAppStatisticsRequestObject(templateId,
531
- eventId,
532
- InAppStatistics.INBOX_INBOX_MESSAGE_UNREAD_KEY, -1, null, null));
754
+ public void inAppMarkAsUnRead(double templateId, String eventId) {
755
+ // no-op in v7
533
756
  }
534
757
 
758
+ /**
759
+ * @see #inAppMarkAsRead
760
+ */
535
761
  @ReactMethod
536
- public void inAppMarkAsDeleted(Integer templateId, String eventId) {
537
- Appoxee.instance().triggerStatistcs((reactContext.getApplicationContext()),
538
- getInAppStatisticsRequestObject(templateId,
539
- eventId,
540
- InAppStatistics.INBOX_INBOX_MESSAGE_DELETED_KEY, -1, null, null));
762
+ public void inAppMarkAsDeleted(double templateId, String eventId) {
763
+ // no-op in v7
541
764
  }
542
765
 
766
+ /**
767
+ * @see #inAppMarkAsRead
768
+ */
543
769
  @ReactMethod
544
- public void triggerStatistic(Integer templateId, String originalEventId,
545
- String trackingKey, int displayMillis,
770
+ public void triggerStatistic(double templateId, String originalEventId,
771
+ String trackingKey, double displayMillis,
546
772
  String reason, String link) {
547
- Appoxee.instance()
548
- .triggerStatistcs((reactContext.getApplicationContext()), getInAppStatisticsRequestObject(templateId,
549
- originalEventId, trackingKey, displayMillis, reason, link));
773
+ // no-op in v7
550
774
  }
551
775
 
552
- @ReactMethod
553
- public void isDeviceRegistered(Promise promise) {
554
- promise.resolve(Appoxee.instance().isDeviceRegistered());
555
- }
776
+ // -------------------------------------------------------------------------
777
+ // Event listeners (pass-through to EventEmitter)
778
+ // -------------------------------------------------------------------------
556
779
 
557
780
  @ReactMethod
558
781
  public void addAndroidListener(String eventName) {
@@ -560,159 +783,86 @@ public class RNMappPluginModule extends ReactContextBaseJavaModule {
560
783
  }
561
784
 
562
785
  @ReactMethod
563
- public void removeAndroidListeners(int count) {
564
- EventEmitter.shared().removeAndroidListeners(count);
786
+ public void removeAndroidListeners(double count) {
787
+ EventEmitter.shared().removeAndroidListeners((int) count);
565
788
  }
566
789
 
567
- // Required for rn built in EventEmitter Calls.
568
790
  @ReactMethod
569
791
  public void addListener(String eventName) {
570
792
  addAndroidListener(eventName);
571
793
  }
572
794
 
573
795
  @ReactMethod
574
- public void removeListeners(Integer count) {
796
+ public void removeListeners(double count) {
575
797
  removeAndroidListeners(count);
576
798
  }
577
799
 
800
+ // -------------------------------------------------------------------------
801
+ // Notifications
802
+ // -------------------------------------------------------------------------
803
+
578
804
  @ReactMethod
579
- public void getDeviceDmcInfo(final Promise promise) {
580
- try {
581
- Map<String, String> map = Appoxee.instance().getDmcDeviceInfo();
582
- WritableMap wm = new WritableNativeMap();
583
- for (Map.Entry<String, String> item : map.entrySet()) {
584
- wm.putString(item.getKey(), item.getValue());
585
- }
586
- promise.resolve(wm);
587
- } catch (Exception e) {
588
- promise.reject("Error getting DMC Info", e);
589
- }
805
+ public void clearNotifications() {
806
+ NotificationManagerCompat.from(reactContext.getApplicationContext()).cancelAll();
590
807
  }
591
808
 
592
- private static InAppStatistics getInAppStatisticsRequestObject(int templateId, String originalEventId,
593
- String trackingKey, int displayMillis,
594
- String reason, String link) {
595
-
596
- InAppStatistics inAppStatistics = new InAppStatistics();
597
- // This will be received from the respective Screens.
598
- MessageContext mc = new MessageContext();
599
- mc.setTemplateId(templateId);
600
- mc.setOriginialEventid(originalEventId);
601
- inAppStatistics.setMessageContext(mc);
602
- Tracking tk = new Tracking();
603
- tk.setTrackingKey(trackingKey);
604
- TrackingAttributes ta = new TrackingAttributes();
605
- int displayTime = displayMillis >= 0 ? displayMillis : -1;
606
- if (displayTime > 0) {
607
- ta.setTimeSinceDisplayMillis((long) displayMillis);
608
- }
609
- ta.setReason(reason);
610
- ta.setLink(link);
611
- tk.setTrackingAttributes(ta);
612
- inAppStatistics.setTracking(tk);
613
-
614
- return inAppStatistics;
615
-
809
+ @ReactMethod
810
+ public void clearNotification(double id) {
811
+ NotificationManagerCompat.from(reactContext.getApplicationContext()).cancel((int) id);
616
812
  }
617
813
 
618
- private WritableMap messageToJson(APXInboxMessage msg) {
619
- WritableMap msgJson = new WritableNativeMap();
620
-
621
- try {
622
- msgJson.putInt("templateId", msg.getTemplateId());
623
- msgJson.putString("title", msg.getContent());
624
- msgJson.putString("eventId", msg.getEventId());
625
- if (msg.getExpirationDate() != null)
626
- msgJson.putString("expirationDate", msg.getExpirationDate().toString());
627
- if (msg.getIconUrl() != null)
628
- msgJson.putString("iconURl", msg.getIconUrl());
629
- if (msg.getStatus() != null)
630
- msgJson.putString("status", msg.getStatus());
631
- if (msg.getSubject() != null)
632
- msgJson.putString("subject", msg.getSubject());
633
- if (msg.getSummary() != null)
634
- msgJson.putString("summary", msg.getSummary());
635
- if (msg.getExtras() != null)
636
- for (ApxInAppExtras apxInAppExtras : msg.getExtras())
637
- msgJson.putString(apxInAppExtras.getName(), apxInAppExtras.getValue());
814
+ // -------------------------------------------------------------------------
815
+ // Session
816
+ // -------------------------------------------------------------------------
638
817
 
639
- } catch (Exception e) {
640
- e.printStackTrace();
641
- }
642
-
643
- return msgJson;
818
+ @ReactMethod
819
+ public void logOut(boolean pushEnabled) {
820
+ Appoxee.instance().logout(pushEnabled).enqueue(result -> {
821
+ });
644
822
  }
645
823
 
646
- private WritableMap getDeviceInfoJson(DeviceInfo deviceInfoList) {
647
- WritableMap deviceInfo = new WritableNativeMap();
648
- try {
649
- deviceInfo.putString("id", deviceInfoList.id);
650
- deviceInfo.putString("appVersion", deviceInfoList.appVersion);
651
- deviceInfo.putString("sdkVersion", deviceInfoList.sdkVersion);
652
- deviceInfo.putString("locale", deviceInfoList.locale);
653
- deviceInfo.putString("timezone", deviceInfoList.timezone);
654
- deviceInfo.putString("deviceModel", deviceInfoList.deviceModel);
655
- deviceInfo.putString("manufacturer", deviceInfoList.manufacturer);
656
- deviceInfo.putString("osVersion", deviceInfoList.osVersion);
657
- deviceInfo.putString("resolution", deviceInfoList.resolution);
658
- deviceInfo.putString("density", String.valueOf(deviceInfoList.density));
659
- } catch (Exception e) {
660
- e.printStackTrace();
661
- }
662
-
663
- return deviceInfo;
664
- }
824
+ // -------------------------------------------------------------------------
825
+ // Private helpers
826
+ // -------------------------------------------------------------------------
665
827
 
666
- public static WritableMap getPushMessageToJSon(PushData pushData) {
667
- WritableMap deviceInfo = new WritableNativeMap();
828
+ static WritableMap messageToJson(@Nullable InboxMessage msg) {
829
+ WritableMap msgJson = new WritableNativeMap();
830
+ if (msg == null) return msgJson;
668
831
  try {
669
- deviceInfo.putString("id", String.valueOf(pushData.id));
670
- deviceInfo.putString("title", pushData.title);
671
- deviceInfo.putString("bigText", pushData.bigText);
672
- deviceInfo.putString("sound", pushData.sound);
673
- if (pushData.actionUri != null)
674
- deviceInfo.putString("actionUri", pushData.actionUri.toString());
675
- deviceInfo.putString("collapseKey", pushData.collapseKey);
676
- deviceInfo.putInt("badgeNumber", pushData.badgeNumber);
677
- deviceInfo.putString("silentType", pushData.silentType);
678
- deviceInfo.putString("silentData", pushData.silentData);
679
- deviceInfo.putString("category", pushData.category);
680
- if (pushData.extraFields != null)
681
- for (Map.Entry<String, String> entry : pushData.extraFields.entrySet()) {
682
- String key = entry.getKey();
683
- String value = entry.getValue();
684
- deviceInfo.putString(key, value);
832
+ msgJson.putInt("templateId", (int) (long) msg.getTemplateId());
833
+ msgJson.putString("title", msg.getContent() != null ? msg.getContent() : "");
834
+ if (msg.getSubject() != null) msgJson.putString("subject", msg.getSubject());
835
+ if (msg.getSummary() != null) msgJson.putString("summary", msg.getSummary());
836
+ if (msg.getIconUrl() != null) msgJson.putString("iconURl", msg.getIconUrl());
837
+ if (msg.getStatus() != null) msgJson.putString("status", msg.getStatus().name());
838
+ if (msg.getExpireDate() != null)
839
+ msgJson.putString("expirationDate", msg.getExpireDate().toString());
840
+ if (msg.getExtras() != null) {
841
+ for (Map.Entry<String, String> entry : msg.getExtras().entrySet()) {
842
+ msgJson.putString(entry.getKey(), entry.getValue());
685
843
  }
844
+ }
686
845
  } catch (Exception e) {
687
846
  e.printStackTrace();
688
847
  }
689
-
690
- return deviceInfo;
848
+ return msgJson;
691
849
  }
692
850
 
693
- private RemoteMessage getRemoteMessage(String jsonMsg) {
694
- if (jsonMsg == null)
695
- return null;
851
+ static RemoteMessage getRemoteMessage(String jsonMsg) {
852
+ if (jsonMsg == null) return null;
696
853
 
697
- final String KEY_TOKEN = "token";
698
854
  final String KEY_COLLAPSE_KEY = "collapseKey";
699
855
  final String KEY_DATA = "data";
700
- final String KEY_FROM = "from";
701
856
  final String KEY_MESSAGE_ID = "messageId";
702
857
  final String KEY_MESSAGE_TYPE = "messageType";
703
- final String KEY_SENT_TIME = "sentTime";
704
- final String KEY_ERROR = "error";
705
- final String KEY_TO = "to";
706
858
  final String KEY_TTL = "ttl";
707
859
 
708
- JSONObject json = null;
709
860
  try {
710
- json = new JSONObject(jsonMsg);
711
-
712
- String collapseKey = json.has(KEY_COLLAPSE_KEY) ? json.getString(KEY_COLLAPSE_KEY) : "";
713
- String messageId = json.has(KEY_MESSAGE_ID) ? json.getString(KEY_MESSAGE_ID) : "";
714
- String messageType = json.has(KEY_MESSAGE_TYPE) ? json.getString(KEY_MESSAGE_TYPE) : "";
715
- int ttl = json.has(KEY_TTL) ? json.getInt(KEY_TTL) : 0;
861
+ JSONObject json = new JSONObject(jsonMsg);
862
+ String collapseKey = json.optString(KEY_COLLAPSE_KEY, "");
863
+ String messageId = json.optString(KEY_MESSAGE_ID, "");
864
+ String messageType = json.optString(KEY_MESSAGE_TYPE, "");
865
+ int ttl = json.optInt(KEY_TTL, 0);
716
866
  JSONObject data = json.has(KEY_DATA) ? json.getJSONObject(KEY_DATA) : null;
717
867
 
718
868
  RemoteMessage.Builder builder = new RemoteMessage.Builder("appoxee@gcm.googleapis.com")
@@ -727,37 +877,10 @@ public class RNMappPluginModule extends ReactContextBaseJavaModule {
727
877
  builder.addData(k, data.getString(k));
728
878
  }
729
879
  }
730
-
731
880
  return builder.build();
732
881
  } catch (JSONException e) {
733
882
  e.printStackTrace();
734
883
  }
735
884
  return null;
736
885
  }
737
-
738
- private boolean shouldRequestLocationPermissions() {
739
- if (Build.VERSION.SDK_INT < 23) {
740
- return false;
741
- }
742
-
743
- return ContextCompat.checkSelfPermission(getReactApplicationContext(),
744
- Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_DENIED &&
745
- ContextCompat.checkSelfPermission(getReactApplicationContext(),
746
- Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED;
747
- }
748
-
749
- @ReactMethod
750
- public void clearNotifications() {
751
- NotificationManagerCompat.from(reactContext.getApplicationContext()).cancelAll();
752
- }
753
-
754
- @ReactMethod
755
- public void clearNotification(int id) {
756
- NotificationManagerCompat.from(reactContext.getApplicationContext()).cancel(id);
757
- }
758
-
759
- @ReactMethod
760
- public void logOut(boolean pushEnabled) {
761
- Appoxee.instance().logOut(application, pushEnabled);
762
- }
763
- }
886
+ }