react-native-notify-kit 10.1.0 → 10.2.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 (52) hide show
  1. package/README.md +99 -96
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/AndroidManifest.xml +0 -1
  4. package/android/src/main/java/app/notifee/core/ForegroundService.java +1 -0
  5. package/android/src/main/java/app/notifee/core/NotificationManager.java +21 -8
  6. package/android/src/main/java/app/notifee/core/RebootBroadcastReceiver.java +16 -0
  7. package/android/src/main/java/app/notifee/core/ReceiverService.java +18 -13
  8. package/android/src/main/java/app/notifee/core/model/NotificationAndroidActionModel.java +1 -2
  9. package/android/src/main/java/app/notifee/core/model/NotificationAndroidPressActionModel.java +3 -9
  10. package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +42 -27
  11. package/android/src/main/java/app/notifee/core/utility/IntentUtils.java +0 -28
  12. package/android/src/main/java/app/notifee/core/utility/PowerManagerUtils.java +79 -41
  13. package/android/src/main/java/app/notifee/core/utility/ResourceUtils.java +5 -1
  14. package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +6 -6
  15. package/android/src/main/kotlin/io/invertase/notifee/NotifeeReactUtils.kt +1 -2
  16. package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +150 -0
  17. package/cli/dist/lib/patchPodfile.d.ts +3 -1
  18. package/cli/dist/lib/patchPodfile.js +125 -33
  19. package/cli/dist/lib/patchPodfile.js.map +1 -1
  20. package/dist/index.d.ts +2 -0
  21. package/dist/types/Module.d.ts +27 -13
  22. package/dist/types/Notification.d.ts +1 -1
  23. package/dist/types/NotificationIOS.d.ts +44 -21
  24. package/dist/types/NotificationIOS.js +15 -1
  25. package/dist/types/NotificationIOS.js.map +1 -1
  26. package/dist/types/PowerManagerInfo.d.ts +9 -4
  27. package/dist/types/Trigger.d.ts +45 -2
  28. package/dist/types/Trigger.js +22 -0
  29. package/dist/types/Trigger.js.map +1 -1
  30. package/dist/validators/validateIOSCategory.js +2 -2
  31. package/dist/validators/validateIOSCategory.js.map +1 -1
  32. package/dist/validators/validateTrigger.js +26 -1
  33. package/dist/validators/validateTrigger.js.map +1 -1
  34. package/dist/version.d.ts +1 -1
  35. package/dist/version.js +1 -1
  36. package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.m +20 -10
  37. package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.h +1 -2
  38. package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m +44 -35
  39. package/ios/NotifeeCore/NotifeeCore.m +1042 -119
  40. package/ios/NotifeeCore/NotifeeCoreUtil.h +36 -1
  41. package/ios/NotifeeCore/NotifeeCoreUtil.m +533 -9
  42. package/ios/RNNotifee/NotifeeApiModule.mm +2 -2
  43. package/package.json +1 -1
  44. package/src/index.ts +2 -0
  45. package/src/types/Module.ts +27 -13
  46. package/src/types/Notification.ts +1 -1
  47. package/src/types/NotificationIOS.ts +43 -28
  48. package/src/types/PowerManagerInfo.ts +9 -4
  49. package/src/types/Trigger.ts +45 -1
  50. package/src/validators/validateIOSCategory.ts +4 -2
  51. package/src/validators/validateTrigger.ts +38 -0
  52. package/src/version.ts +1 -1
@@ -21,6 +21,7 @@ import static app.notifee.core.event.NotificationEvent.TYPE_ACTION_PRESS;
21
21
  import static app.notifee.core.event.NotificationEvent.TYPE_DISMISSED;
22
22
  import static app.notifee.core.event.NotificationEvent.TYPE_PRESS;
23
23
 
24
+ import android.annotation.SuppressLint;
24
25
  import android.app.PendingIntent;
25
26
  import android.app.Service;
26
27
  import android.content.Context;
@@ -171,10 +172,6 @@ public class ReceiverService extends Service {
171
172
  }
172
173
  }
173
174
 
174
- // ACTION_CLOSE_SYSTEM_DIALOGS is deprecated since API 31, but is still needed on API < 31
175
- // to close the notification drawer after an action press. Already guarded with Build.VERSION
176
- // check.
177
- @SuppressWarnings("deprecation")
178
175
  private void onActionPressIntent(Intent intent) {
179
176
  Bundle notification = intent.getBundleExtra("notification");
180
177
  Bundle pressAction = intent.getBundleExtra("pressAction");
@@ -221,16 +218,24 @@ public class ReceiverService extends Service {
221
218
  mainComponent,
222
219
  pressActionBundle.getLaunchActivityFlags());
223
220
 
224
- int targetSdkVersion =
225
- ContextHolder.getApplicationContext().getApplicationInfo().targetSdkVersion;
221
+ closeSystemDialogsBestEffort();
222
+ }
223
+ }
226
224
 
227
- // Close notification drawer if application SDK is Android 11 and lower
228
- // See
229
- // https://developer.android.com/about/versions/12/behavior-changes-all#close-system-dialogs
230
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
231
- ContextHolder.getApplicationContext()
232
- .sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
233
- }
225
+ @SuppressWarnings("deprecation")
226
+ @SuppressLint("MissingPermission")
227
+ private void closeSystemDialogsBestEffort() {
228
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
229
+ return;
230
+ }
231
+
232
+ // BROADCAST_CLOSE_SYSTEM_DIALOGS is protected/system-only, so the library intentionally does
233
+ // not declare it. Keep this pre-Android 12 legacy broadcast best-effort; Android 12+ skips it.
234
+ try {
235
+ ContextHolder.getApplicationContext()
236
+ .sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
237
+ } catch (SecurityException e) {
238
+ Logger.w(TAG, "Unable to close system dialogs with legacy broadcast", e);
234
239
  }
235
240
  }
236
241
 
@@ -77,8 +77,7 @@ public class NotificationAndroidActionModel {
77
77
  * @return RemoteInput
78
78
  */
79
79
  public @Nullable RemoteInput getRemoteInput(NotificationCompat.Action.Builder actionBuilder) {
80
- if (mNotificationAndroidActionBundle.containsKey("input")
81
- && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT_WATCH) {
80
+ if (mNotificationAndroidActionBundle.containsKey("input")) {
82
81
  Bundle inputBundle =
83
82
  Objects.requireNonNull(mNotificationAndroidActionBundle.getBundle("input"));
84
83
 
@@ -105,9 +105,7 @@ public class NotificationAndroidPressActionModel {
105
105
  baseFlags |= Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;
106
106
  break;
107
107
  case 12:
108
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
109
- baseFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
110
- }
108
+ baseFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
111
109
  break;
112
110
  case 13:
113
111
  baseFlags |= Intent.FLAG_ACTIVITY_NO_USER_ACTION;
@@ -125,14 +123,10 @@ public class NotificationAndroidPressActionModel {
125
123
  baseFlags |= Intent.FLAG_ACTIVITY_TASK_ON_HOME;
126
124
  break;
127
125
  case 18:
128
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
129
- baseFlags |= Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
130
- }
126
+ baseFlags |= Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
131
127
  break;
132
128
  case 19:
133
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
134
- baseFlags |= Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
135
- }
129
+ baseFlags |= Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
136
130
  break;
137
131
  case 20:
138
132
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@@ -30,13 +30,13 @@ public class TimestampTriggerModel {
30
30
  private Boolean mWithAlarmManager = false;
31
31
  private AlarmType mAlarmType = AlarmType.SET_EXACT;
32
32
  private String mRepeatFrequency = null;
33
+ private int mRepeatInterval = 1;
33
34
  private Long mTimestamp = null;
34
35
 
35
36
  public static final String HOURLY = "HOURLY";
36
37
  public static final String DAILY = "DAILY";
37
38
  public static final String WEEKLY = "WEEKLY";
38
-
39
- private static final long HOUR_IN_MS = 60L * 60 * 1000;
39
+ public static final String MONTHLY = "MONTHLY";
40
40
 
41
41
  private static final String TAG = "TimeTriggerModel";
42
42
 
@@ -47,6 +47,7 @@ public class TimestampTriggerModel {
47
47
  TimeUnit timeUnit = null;
48
48
  if (mTimeTriggerBundle.containsKey("repeatFrequency")) {
49
49
  int repeatFrequency = ObjectUtils.getInt(mTimeTriggerBundle.get("repeatFrequency"));
50
+ mRepeatInterval = getRepeatInterval(mTimeTriggerBundle.get("repeatInterval"));
50
51
  mTimestamp = ObjectUtils.getLong(mTimeTriggerBundle.get("timestamp"));
51
52
 
52
53
  switch (repeatFrequency) {
@@ -54,21 +55,24 @@ public class TimestampTriggerModel {
54
55
  // default value for one-time trigger
55
56
  break;
56
57
  case 0:
57
- mInterval = 1;
58
+ mInterval = mRepeatInterval;
58
59
  mTimeUnit = TimeUnit.HOURS;
59
60
  mRepeatFrequency = HOURLY;
60
61
  break;
61
62
  case 1:
62
- mInterval = 1;
63
+ mInterval = mRepeatInterval;
63
64
  mTimeUnit = TimeUnit.DAYS;
64
65
  mRepeatFrequency = DAILY;
65
66
  break;
66
67
  case 2:
67
68
  // weekly, 7 days
68
- mInterval = 7;
69
+ mInterval = 7 * mRepeatInterval;
69
70
  mTimeUnit = TimeUnit.DAYS;
70
71
  mRepeatFrequency = WEEKLY;
71
72
  break;
73
+ case 3:
74
+ mRepeatFrequency = MONTHLY;
75
+ break;
72
76
  }
73
77
  }
74
78
 
@@ -139,33 +143,27 @@ public class TimestampTriggerModel {
139
143
  return;
140
144
  }
141
145
 
142
- long timestamp = getTimestamp();
146
+ Calendar cal = Calendar.getInstance();
147
+ cal.setTimeInMillis(getTimestamp());
143
148
 
149
+ int field;
144
150
  if (HOURLY.equals(mRepeatFrequency)) {
145
- // Hourly: fixed ms is correct — no wall-clock preservation needed
146
- while (timestamp < System.currentTimeMillis()) {
147
- timestamp += HOUR_IN_MS;
148
- }
149
- this.mTimestamp = timestamp;
151
+ field = Calendar.HOUR_OF_DAY;
152
+ } else if (DAILY.equals(mRepeatFrequency)) {
153
+ field = Calendar.DAY_OF_MONTH;
154
+ } else if (WEEKLY.equals(mRepeatFrequency)) {
155
+ field = Calendar.WEEK_OF_YEAR;
156
+ } else if (MONTHLY.equals(mRepeatFrequency)) {
157
+ field = Calendar.MONTH;
150
158
  } else {
151
- // Daily/Weekly: use Calendar.add() to preserve local wall-clock time across DST boundaries.
152
- // Adding fixed ms (86,400,000) breaks when a calendar day is 23 or 25 hours during DST.
153
- Calendar cal = Calendar.getInstance();
154
- cal.setTimeInMillis(timestamp);
155
-
156
- int field;
157
- if (WEEKLY.equals(mRepeatFrequency)) {
158
- field = Calendar.WEEK_OF_YEAR;
159
- } else {
160
- field = Calendar.DAY_OF_MONTH;
161
- }
162
-
163
- while (cal.getTimeInMillis() < System.currentTimeMillis()) {
164
- cal.add(field, 1);
165
- }
159
+ return;
160
+ }
166
161
 
167
- this.mTimestamp = cal.getTimeInMillis();
162
+ while (cal.getTimeInMillis() < System.currentTimeMillis()) {
163
+ cal.add(field, mRepeatInterval);
168
164
  }
165
+
166
+ this.mTimestamp = cal.getTimeInMillis();
169
167
  }
170
168
 
171
169
  public enum AlarmType {
@@ -196,6 +194,23 @@ public class TimestampTriggerModel {
196
194
  return mRepeatFrequency;
197
195
  }
198
196
 
197
+ private int getRepeatInterval(Object repeatInterval) {
198
+ if (!(repeatInterval instanceof Number)) {
199
+ return 1;
200
+ }
201
+
202
+ double interval = ((Number) repeatInterval).doubleValue();
203
+ if (Double.isNaN(interval)
204
+ || Double.isInfinite(interval)
205
+ || interval <= 0
206
+ || interval % 1 != 0
207
+ || interval > Integer.MAX_VALUE) {
208
+ return 1;
209
+ }
210
+
211
+ return (int) interval;
212
+ }
213
+
199
214
  public Bundle toBundle() {
200
215
  Bundle bundle = (Bundle) mTimeTriggerBundle.clone();
201
216
  if (mTimestamp != null) {
@@ -22,40 +22,12 @@ import static app.notifee.core.ContextHolder.getApplicationContext;
22
22
  import android.app.Activity;
23
23
  import android.content.Context;
24
24
  import android.content.Intent;
25
- import android.content.pm.PackageManager;
26
- import android.content.pm.ResolveInfo;
27
- import android.os.Build;
28
25
  import androidx.annotation.Nullable;
29
26
  import app.notifee.core.Logger;
30
- import java.util.List;
31
27
 
32
28
  public class IntentUtils {
33
29
  private static final String TAG = "IntentUtils";
34
30
 
35
- @SuppressWarnings("deprecation")
36
- public static boolean isAvailableOnDevice(Context ctx, Intent intent) {
37
- try {
38
- if (ctx == null || intent == null) {
39
- return false;
40
- }
41
-
42
- final PackageManager mgr = ctx.getPackageManager();
43
- List<ResolveInfo> list;
44
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
45
- list =
46
- mgr.queryIntentActivities(
47
- intent, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY));
48
- } else {
49
- list = mgr.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
50
- }
51
- return !list.isEmpty();
52
- } catch (Exception e) {
53
- Logger.e(TAG, "An error occurred whilst trying to check if intent is available on device", e);
54
-
55
- return false;
56
- }
57
- }
58
-
59
31
  public static String getActivityName(Intent intent) {
60
32
  if (intent == null) {
61
33
  return null;
@@ -18,6 +18,7 @@ package app.notifee.core.utility;
18
18
  */
19
19
 
20
20
  import android.app.Activity;
21
+ import android.content.ActivityNotFoundException;
21
22
  import android.content.ComponentName;
22
23
  import android.content.Context;
23
24
  import android.content.Intent;
@@ -55,24 +56,12 @@ public class PowerManagerUtils {
55
56
  * @param activity
56
57
  */
57
58
  public static void openBatteryOptimizationSettings(Activity activity) {
58
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
59
- return;
60
- }
61
-
62
59
  try {
63
60
  Intent intent = new Intent();
64
61
  intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
65
62
  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
66
63
 
67
64
  if (activity != null) {
68
- Boolean isAvailableOnDevice =
69
- IntentUtils.isAvailableOnDevice(ContextHolder.getApplicationContext(), intent);
70
-
71
- if (!isAvailableOnDevice) {
72
- Logger.d(TAG, "battery optimization settings is not available on device");
73
- return;
74
- }
75
-
76
65
  IntentUtils.startActivityOnUiThread(activity, intent);
77
66
  }
78
67
  } catch (Exception e) {
@@ -86,9 +75,6 @@ public class PowerManagerUtils {
86
75
  * @param context
87
76
  */
88
77
  public static Boolean isBatteryOptimizationEnabled(Context context) {
89
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
90
- return false;
91
- }
92
78
  PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
93
79
  return !pm.isIgnoringBatteryOptimizations(context.getPackageName());
94
80
  }
@@ -129,7 +115,7 @@ public class PowerManagerUtils {
129
115
  public static PowerManagerInfo getPowerManagerInfo() {
130
116
  String activityName;
131
117
 
132
- Intent intent = findPowerManagerIntent(ContextHolder.getApplicationContext());
118
+ Intent intent = getFirstPowerManagerIntent();
133
119
  activityName = IntentUtils.getActivityName(intent);
134
120
 
135
121
  PowerManagerInfo result =
@@ -143,37 +129,90 @@ public class PowerManagerUtils {
143
129
  * @param activity
144
130
  */
145
131
  public static void openPowerManagerSettings(Activity activity) {
146
- Intent intent = getPowerManagerIntent();
147
- if (intent == null) {
148
- intent = findPowerManagerIntent(ContextHolder.getApplicationContext());
132
+ if (activity == null) {
133
+ Logger.w(TAG, "Activity is null when trying to open the device's power manager");
134
+ return;
149
135
  }
150
136
 
151
- if (intent != null) {
152
- try {
153
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
154
- IntentUtils.startActivityOnUiThread(activity, intent);
155
- } catch (Exception exception) {
156
- Logger.e(
157
- TAG, "Unable to start activity: " + IntentUtils.getActivityName(intent), exception);
158
- }
159
- } else {
137
+ Context context = ContextHolder.getApplicationContext();
138
+ if (context == null) {
139
+ Logger.w(TAG, "Unable to get application context when opening the device's power manager");
140
+ return;
141
+ }
142
+
143
+ List<Intent> possibleIntents = getPowerManagerIntentCandidates();
144
+ if (possibleIntents.isEmpty()) {
160
145
  Logger.w(TAG, "Unable to find an activity to open the device's power manager");
146
+ return;
147
+ }
148
+
149
+ activity.runOnUiThread(
150
+ () -> {
151
+ for (Intent possibleIntent : possibleIntents) {
152
+ if (startPowerManagerIntent(context, possibleIntent)) {
153
+ return;
154
+ }
155
+ }
156
+
157
+ Logger.w(TAG, "Unable to open the device's power manager");
158
+ });
159
+ }
160
+
161
+ private static Intent getFirstPowerManagerIntent() {
162
+ List<Intent> possibleIntents = getManufacturerPowerManagerIntents(getManufacturerName());
163
+ if (possibleIntents.isEmpty()) {
164
+ return null;
165
+ }
166
+
167
+ return possibleIntents.get(0);
168
+ }
169
+
170
+ private static List<Intent> getPowerManagerIntentCandidates() {
171
+ List<Intent> possibleIntents = new ArrayList<>();
172
+ Intent cachedIntent = getPowerManagerIntent();
173
+
174
+ if (cachedIntent != null) {
175
+ possibleIntents.add(cachedIntent);
161
176
  }
177
+
178
+ for (Intent manufacturerIntent : getManufacturerPowerManagerIntents(getManufacturerName())) {
179
+ if (!containsEquivalentIntent(possibleIntents, manufacturerIntent)) {
180
+ possibleIntents.add(manufacturerIntent);
181
+ }
182
+ }
183
+
184
+ return possibleIntents;
162
185
  }
163
186
 
164
- private static Intent findPowerManagerIntent(Context context) {
165
- String manufacturerName = Build.BRAND.toLowerCase(Locale.US);
166
- List<Intent> possibleIntents = getManufacturerPowerManagerIntents(manufacturerName);
187
+ private static String getManufacturerName() {
188
+ return Build.BRAND.toLowerCase(Locale.US);
189
+ }
167
190
 
168
- for (int i = 0; i < possibleIntents.size(); i++) {
169
- Intent possibleIntent = possibleIntents.get(i);
170
- Boolean isAvailableOnDevice = IntentUtils.isAvailableOnDevice(context, possibleIntent);
171
- if (isAvailableOnDevice) {
172
- setPowerManagerIntentCache(possibleIntent);
173
- return possibleIntent;
191
+ private static boolean containsEquivalentIntent(List<Intent> possibleIntents, Intent candidate) {
192
+ for (Intent possibleIntent : possibleIntents) {
193
+ if (possibleIntent.filterEquals(candidate)) {
194
+ return true;
174
195
  }
175
196
  }
176
- return null;
197
+
198
+ return false;
199
+ }
200
+
201
+ private static boolean startPowerManagerIntent(Context context, Intent possibleIntent) {
202
+ Intent intent = new Intent(possibleIntent);
203
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
204
+
205
+ try {
206
+ context.startActivity(intent);
207
+ setPowerManagerIntentCache(intent);
208
+ return true;
209
+ } catch (ActivityNotFoundException | SecurityException e) {
210
+ Logger.w(TAG, "Unable to start activity: " + IntentUtils.getActivityName(intent), e);
211
+ } catch (RuntimeException e) {
212
+ Logger.w(TAG, "Unable to start activity: " + IntentUtils.getActivityName(intent), e);
213
+ }
214
+
215
+ return false;
177
216
  }
178
217
 
179
218
  private static List<Intent> getManufacturerPowerManagerIntents(String manufacturerName) {
@@ -249,9 +288,8 @@ public class PowerManagerUtils {
249
288
  createIntent(
250
289
  "com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity"),
251
290
  createIntent(
252
- "com.coloros.safecenter",
253
- "com.coloros.safecenter.startupapp.StartupAppListActivity")
254
- .setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS),
291
+ "com.coloros.safecenter",
292
+ "com.coloros.safecenter.startupapp.StartupAppListActivity"),
255
293
  createIntent(
256
294
  "com.coloros.oppoguardelf",
257
295
  "com.coloros.powermanager.fuelgaue.PowerUsageModelActivity"),
@@ -17,6 +17,7 @@ package app.notifee.core.utility;
17
17
  *
18
18
  */
19
19
 
20
+ import android.annotation.SuppressLint;
20
21
  import android.content.Context;
21
22
  import android.content.pm.ApplicationInfo;
22
23
  import android.graphics.Bitmap;
@@ -44,6 +45,7 @@ import com.facebook.imagepipeline.request.ImageRequestBuilder;
44
45
  import com.google.common.util.concurrent.ListenableFuture;
45
46
  import com.google.common.util.concurrent.SettableFuture;
46
47
  import java.util.HashMap;
48
+ import java.util.Locale;
47
49
  import java.util.Map;
48
50
 
49
51
  public class ResourceUtils {
@@ -252,12 +254,13 @@ public class ResourceUtils {
252
254
  }
253
255
 
254
256
  /** Attempts to find a resource id by name and type */
257
+ @SuppressLint("DiscouragedApi")
255
258
  private static int getResourceIdByName(String name, String type) {
256
259
  if (name == null || name.isEmpty()) {
257
260
  return 0;
258
261
  }
259
262
 
260
- name = name.toLowerCase().replace("-", "_");
263
+ name = name.toLowerCase(Locale.ROOT).replace("-", "_");
261
264
 
262
265
  String key = name + "_" + type;
263
266
 
@@ -270,6 +273,7 @@ public class ResourceUtils {
270
273
  Context context = ContextHolder.getApplicationContext();
271
274
  String packageName = context.getPackageName();
272
275
 
276
+ // Consumer resource names are provided dynamically from JS, so runtime lookup is intentional.
273
277
  int id = context.getResources().getIdentifier(name, type, packageName);
274
278
  getResourceIdCache().put(key, id);
275
279
  return id;
@@ -157,7 +157,7 @@ class NotifeeApiModule(reactContext: ReactApplicationContext) :
157
157
 
158
158
  override fun openAlarmPermissionSettings(promise: Promise) {
159
159
  Notifee.getInstance()
160
- .openAlarmPermissionSettings(getCurrentActivity()) { e, _ ->
160
+ .openAlarmPermissionSettings(getReactApplicationContext().getCurrentActivity()) { e, _ ->
161
161
  NotifeeReactUtils.promiseResolver(promise, e)
162
162
  }
163
163
  }
@@ -220,7 +220,7 @@ class NotifeeApiModule(reactContext: ReactApplicationContext) :
220
220
 
221
221
  override fun getInitialNotification(promise: Promise) {
222
222
  Notifee.getInstance()
223
- .getInitialNotification(getCurrentActivity()) { e, bundle ->
223
+ .getInitialNotification(getReactApplicationContext().getCurrentActivity()) { e, bundle ->
224
224
  NotifeeReactUtils.promiseResolver(promise, e, bundle)
225
225
  }
226
226
  }
@@ -242,7 +242,7 @@ class NotifeeApiModule(reactContext: ReactApplicationContext) :
242
242
  return
243
243
  }
244
244
 
245
- val activity = getCurrentActivity() as? PermissionAwareActivity
245
+ val activity = getReactApplicationContext().getCurrentActivity() as? PermissionAwareActivity
246
246
  if (activity == null) {
247
247
  Logger.d(
248
248
  "requestPermission",
@@ -277,14 +277,14 @@ class NotifeeApiModule(reactContext: ReactApplicationContext) :
277
277
 
278
278
  override fun openNotificationSettings(channelId: String?, promise: Promise) {
279
279
  Notifee.getInstance()
280
- .openNotificationSettings(channelId, getCurrentActivity()) { e, _ ->
280
+ .openNotificationSettings(channelId, getReactApplicationContext().getCurrentActivity()) { e, _ ->
281
281
  NotifeeReactUtils.promiseResolver(promise, e)
282
282
  }
283
283
  }
284
284
 
285
285
  override fun openBatteryOptimizationSettings(promise: Promise) {
286
286
  Notifee.getInstance()
287
- .openBatteryOptimizationSettings(getCurrentActivity()) { e, _ ->
287
+ .openBatteryOptimizationSettings(getReactApplicationContext().getCurrentActivity()) { e, _ ->
288
288
  NotifeeReactUtils.promiseResolver(promise, e)
289
289
  }
290
290
  }
@@ -305,7 +305,7 @@ class NotifeeApiModule(reactContext: ReactApplicationContext) :
305
305
 
306
306
  override fun openPowerManagerSettings(promise: Promise) {
307
307
  Notifee.getInstance()
308
- .openPowerManagerSettings(getCurrentActivity()) { e, _ ->
308
+ .openPowerManagerSettings(getReactApplicationContext().getCurrentActivity()) { e, _ ->
309
309
  NotifeeReactUtils.promiseResolver(promise, e)
310
310
  }
311
311
  }
@@ -5,7 +5,6 @@
5
5
  package io.invertase.notifee
6
6
 
7
7
  import android.annotation.SuppressLint
8
- import android.os.Build
9
8
  import android.os.Bundle
10
9
  import android.util.Log
11
10
  import androidx.lifecycle.Lifecycle
@@ -138,7 +137,7 @@ object NotifeeReactUtils {
138
137
  try {
139
138
  val service = context.getSystemService("statusbar")
140
139
  val statusbarManager = Class.forName("android.app.StatusBarManager")
141
- val methodName = if (Build.VERSION.SDK_INT >= 17) "collapsePanels" else "collapse"
140
+ val methodName = "collapsePanels"
142
141
  val collapse: Method = statusbarManager.getMethod(methodName)
143
142
  collapse.isAccessible = true
144
143
  collapse.invoke(service)