react-native-notify-kit 10.2.1 → 10.3.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 (42) hide show
  1. package/android/src/main/java/app/notifee/core/ForegroundService.java +3 -1
  2. package/android/src/main/java/app/notifee/core/NotifeeAlarmManager.java +4 -2
  3. package/android/src/main/java/app/notifee/core/NotificationManager.java +28 -35
  4. package/android/src/main/java/app/notifee/core/database/NotifeeCoreDatabase.java +1 -4
  5. package/android/src/main/java/app/notifee/core/model/ChannelModel.java +8 -13
  6. package/android/src/main/java/app/notifee/core/model/IntervalTriggerModel.java +2 -6
  7. package/android/src/main/java/app/notifee/core/model/NotificationAndroidModel.java +28 -33
  8. package/android/src/main/java/app/notifee/core/model/NotificationAndroidStyleModel.java +6 -4
  9. package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +7 -4
  10. package/android/src/main/java/app/notifee/core/utility/BundleValueReader.java +65 -0
  11. package/android/src/main/java/app/notifee/core/utility/ObjectUtils.java +1 -1
  12. package/android/src/main/java/app/notifee/core/utility/ParcelableCompatReader.java +64 -0
  13. package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +3 -2
  14. package/android/src/main/kotlin/io/invertase/notifee/NotifeeInitProvider.kt +0 -26
  15. package/android/src/test/java/app/notifee/core/NotifeeAlarmManagerCurrentBehaviorTest.java +446 -0
  16. package/android/src/test/java/app/notifee/core/NotificationManagerCreateTriggerNotificationCurrentBehaviorTest.java +209 -0
  17. package/android/src/test/java/app/notifee/core/NotificationManagerPressActionOptOutTest.java +181 -0
  18. package/android/src/test/java/app/notifee/core/NotificationReceiverHandlerInitialNotificationTest.java +158 -0
  19. package/android/src/test/java/app/notifee/core/ReceiverServiceInitialNotificationTest.java +169 -0
  20. package/android/src/test/java/app/notifee/core/model/ChannelModelTest.java +117 -0
  21. package/android/src/test/java/app/notifee/core/model/IntervalTriggerModelTest.java +72 -0
  22. package/android/src/test/java/app/notifee/core/model/NotificationAndroidModelTest.java +310 -0
  23. package/android/src/test/java/app/notifee/core/model/NotificationAndroidStyleModelTest.java +155 -0
  24. package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +292 -6
  25. package/android/src/test/java/app/notifee/core/utility/BundleValueReaderTest.java +132 -0
  26. package/android/src/test/java/app/notifee/core/utility/ObjectUtilsTest.java +141 -0
  27. package/android/src/test/java/app/notifee/core/utility/ParcelableCompatReaderTest.java +124 -0
  28. package/android/src/test/java/io/invertase/notifee/HeadlessTaskReactHostTest.java +137 -0
  29. package/android/src/test/java/io/invertase/notifee/NotifeeEventSubscriberRoutingTest.java +271 -0
  30. package/android/src/test/java/io/invertase/notifee/NotifeeReactUtilsDrawerTest.java +24 -0
  31. package/dist/types/Notification.d.ts +5 -2
  32. package/dist/types/Notification.js +5 -2
  33. package/dist/types/Notification.js.map +1 -1
  34. package/dist/types/NotificationAndroid.d.ts +4 -0
  35. package/dist/types/NotificationAndroid.js +4 -0
  36. package/dist/types/NotificationAndroid.js.map +1 -1
  37. package/dist/version.d.ts +1 -1
  38. package/dist/version.js +1 -1
  39. package/package.json +1 -1
  40. package/src/types/Notification.ts +5 -2
  41. package/src/types/NotificationAndroid.ts +4 -0
  42. package/src/version.ts +1 -1
@@ -39,6 +39,7 @@ import app.notifee.core.event.ForegroundServiceEvent;
39
39
  import app.notifee.core.event.NotificationEvent;
40
40
  import app.notifee.core.interfaces.MethodCallResult;
41
41
  import app.notifee.core.model.NotificationModel;
42
+ import app.notifee.core.utility.ParcelableCompatReader;
42
43
 
43
44
  public class ForegroundService extends Service {
44
45
  private static final String TAG = "ForegroundService";
@@ -186,7 +187,8 @@ public class ForegroundService extends Service {
186
187
  if (extras != null) {
187
188
  // Hash code is sent to service to ensure it is kept the same
188
189
  int hashCode = extras.getInt("hashCode");
189
- Notification notification = extras.getParcelable("notification");
190
+ Notification notification =
191
+ ParcelableCompatReader.getParcelable(extras, "notification", Notification.class);
190
192
  Bundle bundle = extras.getBundle("notificationBundle");
191
193
 
192
194
  if (notification != null && bundle != null) {
@@ -37,6 +37,7 @@ import app.notifee.core.model.NotificationAndroidModel;
37
37
  import app.notifee.core.model.NotificationModel;
38
38
  import app.notifee.core.model.TimestampTriggerModel;
39
39
  import app.notifee.core.utility.AlarmUtils;
40
+ import app.notifee.core.utility.BundleValueReader;
40
41
  import app.notifee.core.utility.ExtendedListenableFuture;
41
42
  import app.notifee.core.utility.ObjectUtils;
42
43
  import com.google.common.util.concurrent.FutureCallback;
@@ -195,7 +196,8 @@ class NotifeeAlarmManager {
195
196
  NotificationManager.displayNotification(notificationModel, triggerBundle),
196
197
  voidDisplayedNotification -> {
197
198
  if (triggerBundle.containsKey("repeatFrequency")
198
- && ObjectUtils.getInt(triggerBundle.get("repeatFrequency")) != -1) {
199
+ && BundleValueReader.getIntPreserving(triggerBundle, "repeatFrequency")
200
+ != -1) {
199
201
  TimestampTriggerModel trigger =
200
202
  TimestampTriggerModel.fromBundle(triggerBundle);
201
203
  // scheduleTimestampTriggerNotification() calls setNextTimestamp()
@@ -424,7 +426,7 @@ class NotifeeAlarmManager {
424
426
  NotificationModel notificationModel =
425
427
  NotificationModel.fromBundle(ObjectUtils.bytesToBundle(notificationBytes));
426
428
 
427
- int triggerType = ObjectUtils.getInt(triggerBundle.get("type"));
429
+ int triggerType = BundleValueReader.getIntPreserving(triggerBundle, "type");
428
430
 
429
431
  switch (triggerType) {
430
432
  case 0:
@@ -61,6 +61,7 @@ import app.notifee.core.model.NotificationAndroidPressActionModel;
61
61
  import app.notifee.core.model.NotificationAndroidStyleModel;
62
62
  import app.notifee.core.model.NotificationModel;
63
63
  import app.notifee.core.model.TimestampTriggerModel;
64
+ import app.notifee.core.utility.BundleValueReader;
64
65
  import app.notifee.core.utility.ExtendedListenableFuture;
65
66
  import app.notifee.core.utility.IntentUtils;
66
67
  import app.notifee.core.utility.ObjectUtils;
@@ -168,18 +169,7 @@ class NotificationManager {
168
169
  // so tapping the notification opens the app (defense-in-depth for paths that
169
170
  // bypass the TS validator).
170
171
  // 2. pressAction has the opt-out sentinel id: user explicitly passed
171
- // pressAction: null in JS — pass null to createIntent so no launch intent
172
- // is created (non-tappable notification).
173
- // 3. pressAction is a normal bundle: pass through unchanged.
174
- // Resolve the effective pressAction bundle for the content intent.
175
- // Three cases:
176
- // 1. pressAction is null (absent from bundle, e.g. trigger rehydrated from Room DB
177
- // after app kill): synthesize default { id:'default', launchActivity:'default' }
178
- // so tapping the notification opens the app (defense-in-depth for paths that
179
- // bypass the TS validator).
180
- // 2. pressAction has the opt-out sentinel id: user explicitly passed
181
- // pressAction: null in JS — pass null to createIntent so no launch intent
182
- // is created (non-tappable notification).
172
+ // pressAction: null in JS, so no content intent is created.
183
173
  // 3. pressAction is a normal bundle: pass through unchanged.
184
174
  //
185
175
  // pressActionForIntent → used for creating the launch intent (or null for opt-out)
@@ -205,23 +195,25 @@ class NotificationManager {
205
195
 
206
196
  int targetSdkVersion =
207
197
  ContextHolder.getApplicationContext().getApplicationInfo().targetSdkVersion;
208
- if (targetSdkVersion >= Build.VERSION_CODES.S
209
- && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
210
- builder.setContentIntent(
211
- NotificationPendingIntent.createIntent(
212
- notificationModel.getHashCode(),
213
- pressActionForIntent,
214
- TYPE_PRESS,
215
- new String[] {"notification", "pressAction"},
216
- notificationModel.toBundle(),
217
- pressActionForExtras));
218
- } else {
219
- builder.setContentIntent(
220
- ReceiverService.createIntent(
221
- ReceiverService.PRESS_INTENT,
222
- new String[] {"notification", "pressAction"},
223
- notificationModel.toBundle(),
224
- pressActionForIntent));
198
+ if (pressActionForIntent != null) {
199
+ if (targetSdkVersion >= Build.VERSION_CODES.S
200
+ && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
201
+ builder.setContentIntent(
202
+ NotificationPendingIntent.createIntent(
203
+ notificationModel.getHashCode(),
204
+ pressActionForIntent,
205
+ TYPE_PRESS,
206
+ new String[] {"notification", "pressAction"},
207
+ notificationModel.toBundle(),
208
+ pressActionForExtras));
209
+ } else {
210
+ builder.setContentIntent(
211
+ ReceiverService.createIntent(
212
+ ReceiverService.PRESS_INTENT,
213
+ new String[] {"notification", "pressAction"},
214
+ notificationModel.toBundle(),
215
+ pressActionForIntent));
216
+ }
225
217
  }
226
218
 
227
219
  if (notificationModel.getTitle() != null) {
@@ -744,7 +736,7 @@ class NotificationManager {
744
736
 
745
737
  static ListenableFuture<Void> createTriggerNotification(
746
738
  NotificationModel notificationModel, Bundle triggerBundle) {
747
- int triggerType = ObjectUtils.getInt(triggerBundle.get("type"));
739
+ int triggerType = BundleValueReader.getIntPreserving(triggerBundle, "type");
748
740
  ListenableFuture<Void> scheduleFuture;
749
741
  switch (triggerType) {
750
742
  case 0:
@@ -903,19 +895,19 @@ class NotificationManager {
903
895
  notificationBundle = new Bundle();
904
896
  notificationBundle.putString("id", "" + sbNotification.getId());
905
897
 
906
- Object title = extras.get(Notification.EXTRA_TITLE);
898
+ Object title = BundleValueReader.getValue(extras, Notification.EXTRA_TITLE);
907
899
 
908
900
  if (title != null) {
909
901
  notificationBundle.putString("title", title.toString());
910
902
  }
911
903
 
912
- Object text = extras.get(Notification.EXTRA_TEXT);
904
+ Object text = BundleValueReader.getValue(extras, Notification.EXTRA_TEXT);
913
905
 
914
906
  if (text != null) {
915
907
  notificationBundle.putString("body", text.toString());
916
908
  }
917
909
 
918
- Object subtitle = extras.get(Notification.EXTRA_SUB_TEXT);
910
+ Object subtitle = BundleValueReader.getValue(extras, Notification.EXTRA_SUB_TEXT);
919
911
 
920
912
  if (subtitle != null) {
921
913
  notificationBundle.putString("subtitle", subtitle.toString());
@@ -934,7 +926,8 @@ class NotificationManager {
934
926
 
935
927
  displayNotificationBundle.putString("id", "" + sbNotification.getId());
936
928
  } else {
937
- displayNotificationBundle.putString("id", "" + notificationBundle.get("id"));
929
+ displayNotificationBundle.putString(
930
+ "id", String.valueOf(BundleValueReader.getValue(notificationBundle, "id")));
938
931
  }
939
932
 
940
933
  if (triggerBundle != null) {
@@ -979,7 +972,7 @@ class NotificationManager {
979
972
  if (!shouldIncludeInData(key)) {
980
973
  continue;
981
974
  }
982
- Object value = extras.get(key);
975
+ Object value = BundleValueReader.getValue(extras, key);
983
976
  if (value != null) {
984
977
  dataBundle.putString(key, value.toString());
985
978
  }
@@ -43,10 +43,7 @@ public abstract class NotifeeCoreDatabase extends RoomDatabase {
43
43
  static final ListeningExecutorService databaseWriteListeningExecutor =
44
44
  MoreExecutors.listeningDecorator(databaseWriteExecutor);
45
45
 
46
- /**
47
- * Migrate from: version 1 to version 2 - where the {@link WorkDataEntity} has an extra field:
48
- * alert
49
- */
46
+ /** Migrate from version 1 to version 2 by adding the with_alarm_manager column. */
50
47
  @VisibleForTesting
51
48
  static final Migration MIGRATION_1_2 =
52
49
  new Migration(1, 2) {
@@ -23,7 +23,7 @@ import androidx.annotation.NonNull;
23
23
  import androidx.annotation.Nullable;
24
24
  import androidx.core.app.NotificationCompat;
25
25
  import androidx.core.app.NotificationManagerCompat;
26
- import app.notifee.core.utility.ObjectUtils;
26
+ import app.notifee.core.utility.BundleValueReader;
27
27
  import java.util.ArrayList;
28
28
  import java.util.Objects;
29
29
 
@@ -72,11 +72,8 @@ public class ChannelModel {
72
72
  }
73
73
 
74
74
  public Integer getImportance() {
75
- if (mChannelBundle.containsKey("importance")) {
76
- return ObjectUtils.getInt(mChannelBundle.get("importance"));
77
- }
78
-
79
- return NotificationManagerCompat.IMPORTANCE_DEFAULT;
75
+ return BundleValueReader.getIntPreserving(
76
+ mChannelBundle, "importance", NotificationManagerCompat.IMPORTANCE_DEFAULT);
80
77
  }
81
78
 
82
79
  public @Nullable Integer getLightColor() {
@@ -88,14 +85,11 @@ public class ChannelModel {
88
85
  }
89
86
 
90
87
  public int getVisibility() {
91
- if (mChannelBundle.containsKey("visibility")) {
92
- return ObjectUtils.getInt(mChannelBundle.get("visibility"));
93
- }
94
-
95
- return NotificationCompat.VISIBILITY_PRIVATE;
88
+ return BundleValueReader.getIntPreserving(
89
+ mChannelBundle, "visibility", NotificationCompat.VISIBILITY_PRIVATE);
96
90
  }
97
91
 
98
- // Bundle.getParcelableArrayList returns ArrayList<?>, so the (Integer) cast is inherently
92
+ // BundleValueReader.getArrayListValue returns ArrayList<?>, so the (Integer) cast is inherently
99
93
  // unchecked but correct for our serialization format.
100
94
  @SuppressWarnings("unchecked")
101
95
  public long[] getVibrationPattern() {
@@ -104,7 +98,8 @@ public class ChannelModel {
104
98
  }
105
99
 
106
100
  ArrayList<?> vibrationPattern =
107
- Objects.requireNonNull(mChannelBundle.getParcelableArrayList("vibrationPattern"));
101
+ Objects.requireNonNull(
102
+ BundleValueReader.getArrayListValue(mChannelBundle, "vibrationPattern"));
108
103
 
109
104
  long[] vibrateArray = new long[vibrationPattern.size()];
110
105
 
@@ -20,7 +20,7 @@ package app.notifee.core.model;
20
20
  import android.os.Bundle;
21
21
  import androidx.annotation.NonNull;
22
22
  import app.notifee.core.Logger;
23
- import app.notifee.core.utility.ObjectUtils;
23
+ import app.notifee.core.utility.BundleValueReader;
24
24
  import java.util.concurrent.TimeUnit;
25
25
 
26
26
  public class IntervalTriggerModel {
@@ -54,10 +54,6 @@ public class IntervalTriggerModel {
54
54
  }
55
55
 
56
56
  public int getInterval() {
57
- if (mIntervalTriggerBundle.containsKey("interval")) {
58
- return ObjectUtils.getInt(mIntervalTriggerBundle.get("interval"));
59
- }
60
-
61
- return -1;
57
+ return BundleValueReader.getIntPreserving(mIntervalTriggerBundle, "interval", -1);
62
58
  }
63
59
  }
@@ -29,7 +29,9 @@ import androidx.annotation.RequiresApi;
29
29
  import androidx.core.app.NotificationCompat;
30
30
  import androidx.core.app.NotificationManagerCompat;
31
31
  import app.notifee.core.Logger;
32
+ import app.notifee.core.utility.BundleValueReader;
32
33
  import app.notifee.core.utility.ObjectUtils;
34
+ import app.notifee.core.utility.ParcelableCompatReader;
33
35
  import app.notifee.core.utility.ResourceUtils;
34
36
  import java.util.ArrayList;
35
37
  import java.util.Objects;
@@ -50,7 +52,9 @@ public class NotificationAndroidModel {
50
52
  public @Nullable ArrayList<NotificationAndroidActionModel> getActions() {
51
53
  if (mNotificationAndroidBundle.containsKey("actions")) {
52
54
  ArrayList<Bundle> actionBundles =
53
- Objects.requireNonNull(mNotificationAndroidBundle.getParcelableArrayList("actions"));
55
+ Objects.requireNonNull(
56
+ ParcelableCompatReader.getParcelableArrayList(
57
+ mNotificationAndroidBundle, "actions", Bundle.class));
54
58
  ArrayList<NotificationAndroidActionModel> actions = new ArrayList<>(actionBundles.size());
55
59
 
56
60
  for (Bundle actionBundle : actionBundles) {
@@ -72,7 +76,8 @@ public class NotificationAndroidModel {
72
76
 
73
77
  ArrayList<?> foregroundServiceTypesArrayList =
74
78
  Objects.requireNonNull(
75
- mNotificationAndroidBundle.getParcelableArrayList("foregroundServiceTypes"));
79
+ BundleValueReader.getArrayListValue(
80
+ mNotificationAndroidBundle, "foregroundServiceTypes"));
76
81
 
77
82
  if (foregroundServiceTypesArrayList.isEmpty()) {
78
83
  Logger.w(TAG, "foregroundServiceTypes is empty; treating as absent");
@@ -137,12 +142,8 @@ public class NotificationAndroidModel {
137
142
  * @return Integer
138
143
  */
139
144
  public @Nullable Integer getBadgeIconType() {
140
- if (mNotificationAndroidBundle.containsKey("badgeIconType")) {
141
-
142
- return ObjectUtils.getInt(mNotificationAndroidBundle.get("badgeIconType"));
143
- }
144
-
145
- return NotificationCompat.BADGE_ICON_LARGE;
145
+ return BundleValueReader.getIntPreserving(
146
+ mNotificationAndroidBundle, "badgeIconType", NotificationCompat.BADGE_ICON_LARGE);
146
147
  }
147
148
 
148
149
  /**
@@ -266,11 +267,8 @@ public class NotificationAndroidModel {
266
267
  * @return int
267
268
  */
268
269
  public int getGroupAlertBehaviour() {
269
- if (mNotificationAndroidBundle.containsKey("groupAlertBehavior")) {
270
- return ObjectUtils.getInt(mNotificationAndroidBundle.get("groupAlertBehavior"));
271
- }
272
-
273
- return NotificationCompat.GROUP_ALERT_ALL;
270
+ return BundleValueReader.getIntPreserving(
271
+ mNotificationAndroidBundle, "groupAlertBehavior", NotificationCompat.GROUP_ALERT_ALL);
274
272
  }
275
273
 
276
274
  /**
@@ -327,14 +325,15 @@ public class NotificationAndroidModel {
327
325
  *
328
326
  * @return ArrayList<Integer>
329
327
  */
330
- // Bundle.getParcelableArrayList returns ArrayList<?>, so element casts to String/Integer
328
+ // BundleValueReader.getArrayListValue returns ArrayList<?>, so element casts to String/Integer
331
329
  // are inherently unchecked but correct for our serialization format.
332
330
  @SuppressWarnings("unchecked")
333
331
  public @Nullable ArrayList<Integer> getLights() {
334
332
  if (mNotificationAndroidBundle.containsKey("lights")) {
335
333
  try {
336
334
  ArrayList<?> lightList =
337
- Objects.requireNonNull(mNotificationAndroidBundle.getParcelableArrayList("lights"));
335
+ Objects.requireNonNull(
336
+ BundleValueReader.getArrayListValue(mNotificationAndroidBundle, "lights"));
338
337
  String rawColor = (String) lightList.get(0);
339
338
 
340
339
  ArrayList<Integer> lights = new ArrayList<>(3);
@@ -368,7 +367,7 @@ public class NotificationAndroidModel {
368
367
  */
369
368
  public Integer getNumber() {
370
369
  if (mNotificationAndroidBundle.containsKey("badgeCount")) {
371
- return ObjectUtils.getInt(mNotificationAndroidBundle.get("badgeCount"));
370
+ return BundleValueReader.getIntPreserving(mNotificationAndroidBundle, "badgeCount");
372
371
  }
373
372
 
374
373
  return null;
@@ -403,7 +402,8 @@ public class NotificationAndroidModel {
403
402
  }
404
403
 
405
404
  ArrayList<?> flagsArrayList =
406
- Objects.requireNonNull(mNotificationAndroidBundle.getParcelableArrayList("flags"));
405
+ Objects.requireNonNull(
406
+ BundleValueReader.getArrayListValue(mNotificationAndroidBundle, "flags"));
407
407
 
408
408
  int[] flagsArray = new int[flagsArrayList.size()];
409
409
 
@@ -469,7 +469,9 @@ public class NotificationAndroidModel {
469
469
  return NotificationCompat.PRIORITY_DEFAULT;
470
470
  }
471
471
 
472
- int importance = ObjectUtils.getInt(mNotificationAndroidBundle.get("importance"));
472
+ int importance =
473
+ BundleValueReader.getIntPreserving(
474
+ mNotificationAndroidBundle, "importance", NotificationManagerCompat.IMPORTANCE_DEFAULT);
473
475
  switch (importance) {
474
476
  case NotificationManagerCompat.IMPORTANCE_HIGH:
475
477
  return NotificationCompat.PRIORITY_HIGH;
@@ -494,8 +496,8 @@ public class NotificationAndroidModel {
494
496
  Objects.requireNonNull(mNotificationAndroidBundle.getBundle("progress"));
495
497
 
496
498
  return new AndroidProgress(
497
- ObjectUtils.getInt(progressBundle.get("max")),
498
- ObjectUtils.getInt(progressBundle.get("current")),
499
+ BundleValueReader.getIntPreserving(progressBundle, "max"),
500
+ BundleValueReader.getIntPreserving(progressBundle, "current"),
499
501
  progressBundle.getBoolean("indeterminate", false));
500
502
  }
501
503
 
@@ -607,7 +609,7 @@ public class NotificationAndroidModel {
607
609
  */
608
610
  public @Nullable Long getTimeoutAfter() {
609
611
  if (mNotificationAndroidBundle.containsKey("timeoutAfter")) {
610
- return ObjectUtils.getLong(mNotificationAndroidBundle.get("timeoutAfter"));
612
+ return BundleValueReader.getLongPreserving(mNotificationAndroidBundle, "timeoutAfter");
611
613
  }
612
614
 
613
615
  return null;
@@ -635,7 +637,7 @@ public class NotificationAndroidModel {
635
637
  *
636
638
  * @return long[]
637
639
  */
638
- // Bundle.getParcelableArrayList returns ArrayList<?>, so the (Integer) cast is inherently
640
+ // BundleValueReader.getArrayListValue returns ArrayList<?>, so the (Integer) cast is inherently
639
641
  // unchecked but correct for our serialization format.
640
642
  @SuppressWarnings("unchecked")
641
643
  public long[] getVibrationPattern() {
@@ -645,7 +647,7 @@ public class NotificationAndroidModel {
645
647
 
646
648
  ArrayList<?> vibrationPattern =
647
649
  Objects.requireNonNull(
648
- mNotificationAndroidBundle.getParcelableArrayList("vibrationPattern"));
650
+ BundleValueReader.getArrayListValue(mNotificationAndroidBundle, "vibrationPattern"));
649
651
 
650
652
  long[] vibrateArray = new long[vibrationPattern.size()];
651
653
 
@@ -663,11 +665,8 @@ public class NotificationAndroidModel {
663
665
  * @return int
664
666
  */
665
667
  public int getVisibility() {
666
- if (mNotificationAndroidBundle.containsKey("visibility")) {
667
- return ObjectUtils.getInt(mNotificationAndroidBundle.get("visibility"));
668
- }
669
-
670
- return NotificationCompat.VISIBILITY_PRIVATE;
668
+ return BundleValueReader.getIntPreserving(
669
+ mNotificationAndroidBundle, "visibility", NotificationCompat.VISIBILITY_PRIVATE);
671
670
  }
672
671
 
673
672
  /**
@@ -676,11 +675,7 @@ public class NotificationAndroidModel {
676
675
  * @return long
677
676
  */
678
677
  public long getTimestamp() {
679
- if (mNotificationAndroidBundle.containsKey("timestamp")) {
680
- return ObjectUtils.getLong(mNotificationAndroidBundle.get("timestamp"));
681
- }
682
-
683
- return -1;
678
+ return BundleValueReader.getLongPreserving(mNotificationAndroidBundle, "timestamp", -1L);
684
679
  }
685
680
 
686
681
  public static class AndroidProgress {
@@ -25,7 +25,8 @@ import androidx.core.app.NotificationCompat;
25
25
  import androidx.core.app.Person;
26
26
  import androidx.core.graphics.drawable.IconCompat;
27
27
  import app.notifee.core.Logger;
28
- import app.notifee.core.utility.ObjectUtils;
28
+ import app.notifee.core.utility.BundleValueReader;
29
+ import app.notifee.core.utility.ParcelableCompatReader;
29
30
  import app.notifee.core.utility.ResourceUtils;
30
31
  import app.notifee.core.utility.TextUtils;
31
32
  import com.google.common.util.concurrent.Futures;
@@ -114,7 +115,7 @@ public class NotificationAndroidStyleModel {
114
115
  @Nullable
115
116
  public ListenableFuture<NotificationCompat.Style> getStyleTask(
116
117
  ListeningExecutorService lExecutor) {
117
- int type = ObjectUtils.getInt(mNotificationAndroidStyleBundle.get("type"));
118
+ int type = BundleValueReader.getIntPreserving(mNotificationAndroidStyleBundle, "type");
118
119
  ListenableFuture<NotificationCompat.Style> styleTask = null;
119
120
 
120
121
  switch (type) {
@@ -312,12 +313,13 @@ public class NotificationAndroidStyleModel {
312
313
  }
313
314
 
314
315
  ArrayList<Bundle> messages =
315
- mNotificationAndroidStyleBundle.getParcelableArrayList("messages");
316
+ ParcelableCompatReader.getParcelableArrayList(
317
+ mNotificationAndroidStyleBundle, "messages", Bundle.class);
316
318
 
317
319
  for (int i = 0; i < Objects.requireNonNull(messages).size(); i++) {
318
320
  Bundle message = messages.get(i);
319
321
  Person messagePerson = null;
320
- long timestamp = ObjectUtils.getLong(message.get("timestamp"));
322
+ long timestamp = BundleValueReader.getLongPreserving(message, "timestamp");
321
323
 
322
324
  if (message.containsKey("person")) {
323
325
  messagePerson =
@@ -19,6 +19,7 @@ package app.notifee.core.model;
19
19
 
20
20
  import android.os.Bundle;
21
21
  import androidx.annotation.NonNull;
22
+ import app.notifee.core.utility.BundleValueReader;
22
23
  import app.notifee.core.utility.ObjectUtils;
23
24
  import java.util.Calendar;
24
25
  import java.util.concurrent.TimeUnit;
@@ -46,9 +47,11 @@ public class TimestampTriggerModel {
46
47
  // set initial values
47
48
  TimeUnit timeUnit = null;
48
49
  if (mTimeTriggerBundle.containsKey("repeatFrequency")) {
49
- int repeatFrequency = ObjectUtils.getInt(mTimeTriggerBundle.get("repeatFrequency"));
50
- mRepeatInterval = getRepeatInterval(mTimeTriggerBundle.get("repeatInterval"));
51
- mTimestamp = ObjectUtils.getLong(mTimeTriggerBundle.get("timestamp"));
50
+ int repeatFrequency =
51
+ BundleValueReader.getIntPreserving(mTimeTriggerBundle, "repeatFrequency");
52
+ mRepeatInterval =
53
+ getRepeatInterval(BundleValueReader.getValue(mTimeTriggerBundle, "repeatInterval"));
54
+ mTimestamp = BundleValueReader.getLongPreserving(mTimeTriggerBundle, "timestamp");
52
55
 
53
56
  switch (repeatFrequency) {
54
57
  case -1:
@@ -81,7 +84,7 @@ public class TimestampTriggerModel {
81
84
 
82
85
  Bundle alarmManagerBundle = mTimeTriggerBundle.getBundle("alarmManager");
83
86
 
84
- Object typeObj = alarmManagerBundle.get("type");
87
+ Object typeObj = BundleValueReader.getValue(alarmManagerBundle, "type");
85
88
 
86
89
  int type;
87
90
  if (typeObj != null) {
@@ -0,0 +1,65 @@
1
+ package app.notifee.core.utility;
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import android.os.Bundle;
21
+ import androidx.annotation.NonNull;
22
+ import androidx.annotation.Nullable;
23
+ import java.util.ArrayList;
24
+
25
+ public final class BundleValueReader {
26
+
27
+ private BundleValueReader() {}
28
+
29
+ @SuppressWarnings("deprecation")
30
+ @Nullable
31
+ public static Object getValue(@NonNull Bundle bundle, @Nullable String key) {
32
+ return bundle.get(key);
33
+ }
34
+
35
+ @Nullable
36
+ public static ArrayList<?> getArrayListValue(@NonNull Bundle bundle, @Nullable String key) {
37
+ return (ArrayList<?>) getValue(bundle, key);
38
+ }
39
+
40
+ public static int getIntPreserving(@NonNull Bundle bundle, @Nullable String key) {
41
+ return ObjectUtils.getInt(getValue(bundle, key));
42
+ }
43
+
44
+ public static int getIntPreserving(
45
+ @NonNull Bundle bundle, @Nullable String key, int defaultValue) {
46
+ if (!bundle.containsKey(key)) {
47
+ return defaultValue;
48
+ }
49
+
50
+ return getIntPreserving(bundle, key);
51
+ }
52
+
53
+ public static long getLongPreserving(@NonNull Bundle bundle, @Nullable String key) {
54
+ return ObjectUtils.getLong(getValue(bundle, key));
55
+ }
56
+
57
+ public static long getLongPreserving(
58
+ @NonNull Bundle bundle, @Nullable String key, long defaultValue) {
59
+ if (!bundle.containsKey(key)) {
60
+ return defaultValue;
61
+ }
62
+
63
+ return getLongPreserving(bundle, key);
64
+ }
65
+ }
@@ -111,7 +111,7 @@ public class ObjectUtils {
111
111
  public static Map<String, Object> bundleToMap(Bundle bundle) throws IllegalArgumentException {
112
112
  Map<String, Object> map = new HashMap<>();
113
113
  for (String key : bundle.keySet()) {
114
- Object value = bundle.get(key);
114
+ Object value = BundleValueReader.getValue(bundle, key);
115
115
  if (value == null) {
116
116
  map.put(key, null);
117
117
  } else if (value.getClass().isArray()) {
@@ -0,0 +1,64 @@
1
+ package app.notifee.core.utility;
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import android.os.Build;
21
+ import android.os.Bundle;
22
+ import android.os.Parcelable;
23
+ import androidx.annotation.NonNull;
24
+ import androidx.annotation.Nullable;
25
+ import java.util.ArrayList;
26
+
27
+ public final class ParcelableCompatReader {
28
+
29
+ private ParcelableCompatReader() {}
30
+
31
+ @Nullable
32
+ public static <T extends Parcelable> T getParcelable(
33
+ @NonNull Bundle bundle, @Nullable String key, @NonNull Class<T> clazz) {
34
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
35
+ return bundle.getParcelable(key, clazz);
36
+ }
37
+
38
+ return getParcelableLegacy(bundle, key);
39
+ }
40
+
41
+ @Nullable
42
+ public static <T extends Parcelable> ArrayList<T> getParcelableArrayList(
43
+ @NonNull Bundle bundle, @Nullable String key, @NonNull Class<T> clazz) {
44
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
45
+ return bundle.getParcelableArrayList(key, clazz);
46
+ }
47
+
48
+ return getParcelableArrayListLegacy(bundle, key);
49
+ }
50
+
51
+ @SuppressWarnings({"deprecation", "unchecked"})
52
+ @Nullable
53
+ private static <T extends Parcelable> T getParcelableLegacy(
54
+ @NonNull Bundle bundle, @Nullable String key) {
55
+ return bundle.getParcelable(key);
56
+ }
57
+
58
+ @SuppressWarnings({"deprecation", "unchecked"})
59
+ @Nullable
60
+ private static <T extends Parcelable> ArrayList<T> getParcelableArrayListLegacy(
61
+ @NonNull Bundle bundle, @Nullable String key) {
62
+ return bundle.getParcelableArrayList(key);
63
+ }
64
+ }
@@ -9,6 +9,7 @@ import android.os.Build
9
9
  import android.os.Bundle
10
10
  import app.notifee.core.Logger
11
11
  import app.notifee.core.Notifee
12
+ import app.notifee.core.WarmupHelper
12
13
  import com.facebook.react.bridge.Arguments
13
14
  import com.facebook.react.bridge.Promise
14
15
  import com.facebook.react.bridge.ReactApplicationContext
@@ -199,7 +200,7 @@ class NotifeeApiModule(reactContext: ReactApplicationContext) :
199
200
 
200
201
  override fun getChannelGroup(channelGroupId: String, promise: Promise) {
201
202
  Notifee.getInstance()
202
- .getChannel(channelGroupId) { e, bundle ->
203
+ .getChannelGroup(channelGroupId) { e, bundle ->
203
204
  NotifeeReactUtils.promiseResolver(promise, e, bundle)
204
205
  }
205
206
  }
@@ -331,7 +332,7 @@ class NotifeeApiModule(reactContext: ReactApplicationContext) :
331
332
  executor.submit {
332
333
  android.os.Trace.beginSection("notifee:prewarm")
333
334
  try {
334
- app.notifee.core.WarmupHelper.runWarmup(context)
335
+ WarmupHelper.runWarmup(context)
335
336
  promise.resolve(null)
336
337
  } catch (t: Throwable) {
337
338
  // Best-effort semantics: warmup failures don't reject the promise.