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.
- package/README.md +99 -96
- package/android/build.gradle +2 -2
- package/android/src/main/AndroidManifest.xml +0 -1
- package/android/src/main/java/app/notifee/core/ForegroundService.java +1 -0
- package/android/src/main/java/app/notifee/core/NotificationManager.java +21 -8
- package/android/src/main/java/app/notifee/core/RebootBroadcastReceiver.java +16 -0
- package/android/src/main/java/app/notifee/core/ReceiverService.java +18 -13
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidActionModel.java +1 -2
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidPressActionModel.java +3 -9
- package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +42 -27
- package/android/src/main/java/app/notifee/core/utility/IntentUtils.java +0 -28
- package/android/src/main/java/app/notifee/core/utility/PowerManagerUtils.java +79 -41
- package/android/src/main/java/app/notifee/core/utility/ResourceUtils.java +5 -1
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +6 -6
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeReactUtils.kt +1 -2
- package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +150 -0
- package/cli/dist/lib/patchPodfile.d.ts +3 -1
- package/cli/dist/lib/patchPodfile.js +125 -33
- package/cli/dist/lib/patchPodfile.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/types/Module.d.ts +27 -13
- package/dist/types/Notification.d.ts +1 -1
- package/dist/types/NotificationIOS.d.ts +44 -21
- package/dist/types/NotificationIOS.js +15 -1
- package/dist/types/NotificationIOS.js.map +1 -1
- package/dist/types/PowerManagerInfo.d.ts +9 -4
- package/dist/types/Trigger.d.ts +45 -2
- package/dist/types/Trigger.js +22 -0
- package/dist/types/Trigger.js.map +1 -1
- package/dist/validators/validateIOSCategory.js +2 -2
- package/dist/validators/validateIOSCategory.js.map +1 -1
- package/dist/validators/validateTrigger.js +26 -1
- package/dist/validators/validateTrigger.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.m +20 -10
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.h +1 -2
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m +44 -35
- package/ios/NotifeeCore/NotifeeCore.m +1042 -119
- package/ios/NotifeeCore/NotifeeCoreUtil.h +36 -1
- package/ios/NotifeeCore/NotifeeCoreUtil.m +533 -9
- package/ios/RNNotifee/NotifeeApiModule.mm +2 -2
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/types/Module.ts +27 -13
- package/src/types/Notification.ts +1 -1
- package/src/types/NotificationIOS.ts +43 -28
- package/src/types/PowerManagerInfo.ts +9 -4
- package/src/types/Trigger.ts +45 -1
- package/src/validators/validateIOSCategory.ts +4 -2
- package/src/validators/validateTrigger.ts +38 -0
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -349,6 +349,7 @@ This fork is a complete migration to React Native's **New Architecture**:
|
|
|
349
349
|
- **Core notification logic (NotifeeCore) is unchanged** — the public API is fully compatible with the original Notifee
|
|
350
350
|
- **35 upstream bugs fixed** — see [Bugs Fixed from Upstream Notifee](#bugs-fixed-from-upstream-notifee) below
|
|
351
351
|
- **Reliable trigger notifications** — AlarmManager is the default backend instead of WorkManager, with automatic fallback when exact alarm permission is not granted
|
|
352
|
+
- **Custom repeat intervals for timestamp triggers** — `TimestampTrigger.repeatInterval` supports calendar-based recurrences such as every 2 days, every 2 weeks, or every 3 months from a selected start timestamp. On iOS, repeating timestamp triggers now use a bounded rolling schedule of one-shot local notifications instead of native repeating calendar triggers; this enables custom repeat intervals and start-date-respecting recurrence, but apps that relied on native iOS repeating triggers being scheduled indefinitely should review the iOS notes in the [Triggers guide](docs/react-native/triggers.mdx#custom-repeat-intervals).
|
|
352
353
|
- **New API: `setNotificationConfig()`** — opt-out flag to prevent Notifee from intercepting iOS remote notification handlers (see [New APIs](#new-apis) below)
|
|
353
354
|
- **Baseline Profile** — the library AAR ships a Baseline Profile that instructs ART to AOT-compile the foreground service notification hot path at install time, eliminating JIT penalty on first invocation
|
|
354
355
|
|
|
@@ -356,44 +357,44 @@ This fork is a complete migration to React Native's **New Architecture**:
|
|
|
356
357
|
|
|
357
358
|
This fork fixes the following bugs that were never resolved in the original Notifee repository:
|
|
358
359
|
|
|
359
|
-
| Bug
|
|
360
|
-
|
|
|
361
|
-
| Notifee intercepts iOS remote notification tap handlers, breaking RNFB `onNotificationOpenedApp` / `getInitialNotification`
|
|
362
|
-
| `completionHandler` not called on notification dismiss
|
|
363
|
-
| `completionHandler` not called in `willPresentNotification` fallback
|
|
364
|
-
| `getInitialNotification()` returns `null` on cold start (deprecated `UIApplicationLaunchOptionsLocalNotificationKey` check)
|
|
365
|
-
| `willPresentNotification:` fallback silently drops foreground notifications when no original delegate is captured (returns `None` instead of platform defaults)
|
|
366
|
-
| All delivered notifications dismissed from Notification Center when the app is opened
|
|
367
|
-
| `getInitialNotification()` returns `null` without `pressAction` configured
|
|
368
|
-
| Foreground press events silently dropped when React instance not ready
|
|
369
|
-
| Trigger notifications not firing on Android 14-15 when app is killed (missing `goAsync()` in `BroadcastReceiver`)
|
|
370
|
-
| `SCHEDULE_EXACT_ALARM` denial silently drops scheduled alarms (no fallback)
|
|
371
|
-
| `getNotificationSettings()` returns `DENIED` instead of `NOT_DETERMINED` on Android 13+ before permission requested
|
|
372
|
-
| Default `AlarmType.SET_EXACT` doesn't work in Doze mode; `AlarmType.SET` uses `RTC` instead of `RTC_WAKEUP`
|
|
373
|
-
| Foreground service crashes with ANR after ~3 min on Android 14+ (`shortService` timeout, missing `onTimeout()`)
|
|
374
|
-
| Manifest merger failure when overriding `foregroundServiceType` on `ForegroundService`
|
|
375
|
-
| Foreground service notifications dismissible on Android 13+ even with `ongoing: true` (library doesn't auto-set `ongoing` for foreground services)
|
|
376
|
-
| DST (daylight saving time) shifts repeating scheduled notifications by ±1 hour
|
|
377
|
-
| `!=` reference equality on String comparison in `NotificationPendingIntent` (latent — would activate when `getLaunchActivity()` returns a non-null value for `id=default`)
|
|
378
|
-
| `pressAction.launchActivity` not defaulted at native layer when `pressAction.id === 'default'`
|
|
379
|
-
| Duplicate symbols linker error when using NSE (`$NotifeeExtension = true`) with static frameworks — `NotifeeExtensionHelper` compiled by both `RNNotifee` and `RNNotifeeCore` pods
|
|
380
|
-
| `Could not resolve app.notifee:core:+` / `FAIL_ON_PROJECT_REPOS` rejection — library injected a Maven repository into the consumer's `rootProject.allprojects` block, which broke on (a) RN 0.74+ with `dependencyResolutionManagement`, (b) Expo SDK 53/54 where `extraMavenRepos` is not propagated to subprojects, and (c) Gradle 8 dependency locking with legacy XML parsers
|
|
381
|
-
| Stale Gradle cache could serve outdated AAR bytecode after `yarn upgrade` — same Maven coordinate reused across releases violated Gradle's coordinate-immutability assumption
|
|
382
|
-
| `EventType.DELIVERED` not emitted for `displayNotification()` in foreground (only for trigger notifications) — `notifeeTrigger != nil` guard in `willPresentNotification:` suppressed the event, breaking iOS/Android symmetry
|
|
383
|
-
| Tapping a notification without explicit `pressAction` does nothing (app doesn't open) — `NotificationPendingIntent.createIntent()` creates a tap-less PendingIntent when `pressActionModelBundle` is null, especially visible on trigger notifications after app kill
|
|
384
|
-
| Foreground service notifications delayed up to 10 seconds on Android 12+ — library never calls `setForegroundServiceBehavior(FOREGROUND_SERVICE_IMMEDIATE)`
|
|
385
|
-
| `didReceiveNotificationResponse:` completionHandler delayed by 15 seconds via `dispatch_after`, blocking subsequent notification taps and risking handler leaks if the app is suspended during the wait
|
|
386
|
-
| `requestPermission:` silently swallows `NSError` from `requestAuthorizationWithOptions`, making MDM and parental-control authorization failures invisible to JS consumers
|
|
387
|
-
| `contentByUpdatingWithProvider:` errors suppressed via `nil` error pointer in `displayNotification:` and `createTriggerNotification:` — communication notifications with malformed SiriKit intents silently fail with nil content
|
|
388
|
-
| `getBadgeCount:` completion block never called when running in an app extension, causing JS promises to hang forever in NSE handlers
|
|
389
|
-
| Notification Service Extension attachment downloads had no timeout cap (default 60-second `NSURLSession` timeout exceeds iOS's ~30-second NSE budget), causing extension process kill and notification loss on slow networks
|
|
390
|
-
| `cancelTriggerNotifications()` / `createTriggerNotification()` promises resolve before Room DB write completes, causing ~3% race on cancel-then-create patterns. Also fixes a previously-undocumented reboot-recovery data-loss bug in `NotifeeAlarmManager.rescheduleNotification` and an ordering bug in `NotificationManager.doScheduledWork`
|
|
391
|
-
| Scheduled trigger notifications silently lost across device reboot on OEM devices (Xiaomi MIUI, OnePlus, Huawei EMUI, Oppo ColorOS, Vivo FuntouchOS) whose vendor OS suppresses `BOOT_COMPLETED` until the user manually enables autostart. Also handles zombie non-repeating triggers whose fire time already passed (fire-once within a 24-hour grace period, then delete the Room row; delete silently beyond the grace period) and adds try/catch/finally guards to all notifee `BroadcastReceiver` async paths. | Android
|
|
392
|
-
| `RepeatFrequency.DAILY` / `WEEKLY` triggers fire on day 1 but never on day 2+ (also reproduces with arrays of 24 daily reminders) — pre-fix: stale Room anchors after the post-fire repeat recalculation, plus DST ±1h shift on repeating triggers, plus reboot recovery silently dropping the rearmed PendingIntent on OEM devices that suppress `BOOT_COMPLETED`
|
|
393
|
-
| Scheduled `TIMESTAMP` trigger notifications lost after device reboot on Android 14 emulator with battery optimizations off — pre-fix: `RebootBroadcastReceiver` dropped the goAsync handoff before Room writes completed; OEM devices that suppress `BOOT_COMPLETED` never re-armed the alarm at all
|
|
394
|
-
| `ObjectAlreadyConsumedException` in headless task when the same `WritableMap` is reused or the `taskConfig` accessor is read twice — `TaskConfig.init` mutated the caller's map instead of copying it first. Latent in most apps but observed in production by upstream users with high-frequency headless events
|
|
395
|
-
| `getDisplayedNotifications()` returned no `data` field on Android, breaking iOS/Android API symmetry where iOS exposes custom keys via `parseDataFromUserInfo:` (see platform limitation note below — the fix is API parity for app-posted notifications, not a workaround for FCM background auto-display)
|
|
396
|
-
| Small icon resolution failure in release builds causes `IllegalArgumentException` at `NotificationCompat.Builder.build()` — library now falls back to the app launcher icon and logs a warning instead of failing the notification display
|
|
360
|
+
| Bug | Platform | Upstream Issue | Fixed in |
|
|
361
|
+
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
362
|
+
| Notifee intercepts iOS remote notification tap handlers, breaking RNFB `onNotificationOpenedApp` / `getInitialNotification` | iOS | [#912](https://github.com/invertase/notifee/issues/912) | 9.1.12 |
|
|
363
|
+
| `completionHandler` not called on notification dismiss | iOS | Pre-existing | 9.1.12 |
|
|
364
|
+
| `completionHandler` not called in `willPresentNotification` fallback | iOS | Pre-existing | 9.1.12 |
|
|
365
|
+
| `getInitialNotification()` returns `null` on cold start (deprecated `UIApplicationLaunchOptionsLocalNotificationKey` check) | iOS | [#1128](https://github.com/invertase/notifee/issues/1128) | 9.1.12 |
|
|
366
|
+
| `willPresentNotification:` fallback silently drops foreground notifications when no original delegate is captured (returns `None` instead of platform defaults) | iOS | Pre-existing (introduced by partial fix in v9.1.12) | 9.1.20 |
|
|
367
|
+
| All delivered notifications dismissed from Notification Center when the app is opened | iOS | [#828](https://github.com/invertase/notifee/issues/828) | 9.1.20 |
|
|
368
|
+
| `getInitialNotification()` returns `null` without `pressAction` configured | Android | [#1128](https://github.com/invertase/notifee/issues/1128) | 9.1.12 |
|
|
369
|
+
| Foreground press events silently dropped when React instance not ready | Android | [#1279](https://github.com/invertase/notifee/issues/1279) | 9.1.12 |
|
|
370
|
+
| Trigger notifications not firing on Android 14-15 when app is killed (missing `goAsync()` in `BroadcastReceiver`) | Android | [#1100](https://github.com/invertase/notifee/issues/1100) | 9.1.12 |
|
|
371
|
+
| `SCHEDULE_EXACT_ALARM` denial silently drops scheduled alarms (no fallback) | Android | [#1100](https://github.com/invertase/notifee/issues/1100) | 9.1.12 |
|
|
372
|
+
| `getNotificationSettings()` returns `DENIED` instead of `NOT_DETERMINED` on Android 13+ before permission requested | Android | [#1237](https://github.com/invertase/notifee/issues/1237) | 9.1.12 |
|
|
373
|
+
| Default `AlarmType.SET_EXACT` doesn't work in Doze mode; `AlarmType.SET` uses `RTC` instead of `RTC_WAKEUP` | Android | [#961](https://github.com/invertase/notifee/issues/961) | 9.1.12 |
|
|
374
|
+
| Foreground service crashes with ANR after ~3 min on Android 14+ (`shortService` timeout, missing `onTimeout()`) | Android | [#703](https://github.com/invertase/notifee/issues/703), [#1107](https://github.com/invertase/notifee/issues/1107) | 9.1.13 |
|
|
375
|
+
| Manifest merger failure when overriding `foregroundServiceType` on `ForegroundService` | Android | [#1108](https://github.com/invertase/notifee/issues/1108) | 9.1.13 |
|
|
376
|
+
| Foreground service notifications dismissible on Android 13+ even with `ongoing: true` (library doesn't auto-set `ongoing` for foreground services) | Android | [#1248](https://github.com/invertase/notifee/issues/1248) | 9.1.14 |
|
|
377
|
+
| DST (daylight saving time) shifts repeating scheduled notifications by ±1 hour | Android | [#875](https://github.com/invertase/notifee/issues/875) | 9.1.14 |
|
|
378
|
+
| `!=` reference equality on String comparison in `NotificationPendingIntent` (latent — would activate when `getLaunchActivity()` returns a non-null value for `id=default`) | Android | Pre-existing (latent) | 9.1.19 |
|
|
379
|
+
| `pressAction.launchActivity` not defaulted at native layer when `pressAction.id === 'default'` | Android | N/A (defense-in-depth) | 9.1.19 |
|
|
380
|
+
| Duplicate symbols linker error when using NSE (`$NotifeeExtension = true`) with static frameworks — `NotifeeExtensionHelper` compiled by both `RNNotifee` and `RNNotifeeCore` pods | iOS | Pre-existing | 9.1.22 |
|
|
381
|
+
| `Could not resolve app.notifee:core:+` / `FAIL_ON_PROJECT_REPOS` rejection — library injected a Maven repository into the consumer's `rootProject.allprojects` block, which broke on (a) RN 0.74+ with `dependencyResolutionManagement`, (b) Expo SDK 53/54 where `extraMavenRepos` is not propagated to subprojects, and (c) Gradle 8 dependency locking with legacy XML parsers | Android | [#1079](https://github.com/invertase/notifee/issues/1079), [#1226](https://github.com/invertase/notifee/issues/1226), [#1262](https://github.com/invertase/notifee/issues/1262) | 9.2.0 |
|
|
382
|
+
| Stale Gradle cache could serve outdated AAR bytecode after `yarn upgrade` — same Maven coordinate reused across releases violated Gradle's coordinate-immutability assumption | Android | N/A (architectural) | 9.2.0 |
|
|
383
|
+
| `EventType.DELIVERED` not emitted for `displayNotification()` in foreground (only for trigger notifications) — `notifeeTrigger != nil` guard in `willPresentNotification:` suppressed the event, breaking iOS/Android symmetry | iOS | Pre-existing | 9.3.0 |
|
|
384
|
+
| Tapping a notification without explicit `pressAction` does nothing (app doesn't open) — `NotificationPendingIntent.createIntent()` creates a tap-less PendingIntent when `pressActionModelBundle` is null, especially visible on trigger notifications after app kill | Android | Pre-existing (latent), [#291](https://github.com/invertase/notifee/issues/291) | 9.3.0 |
|
|
385
|
+
| Foreground service notifications delayed up to 10 seconds on Android 12+ — library never calls `setForegroundServiceBehavior(FOREGROUND_SERVICE_IMMEDIATE)` | Android | [#272](https://github.com/invertase/notifee/issues/272), [#1242](https://github.com/invertase/notifee/issues/1242) | 9.4.0 |
|
|
386
|
+
| `didReceiveNotificationResponse:` completionHandler delayed by 15 seconds via `dispatch_after`, blocking subsequent notification taps and risking handler leaks if the app is suspended during the wait | iOS | Pre-existing (TODO since 2020) | 9.4.0 |
|
|
387
|
+
| `requestPermission:` silently swallows `NSError` from `requestAuthorizationWithOptions`, making MDM and parental-control authorization failures invisible to JS consumers | iOS | Pre-existing (TODO since day 1) | 9.4.0 |
|
|
388
|
+
| `contentByUpdatingWithProvider:` errors suppressed via `nil` error pointer in `displayNotification:` and `createTriggerNotification:` — communication notifications with malformed SiriKit intents silently fail with nil content | iOS | Pre-existing | 9.4.0 |
|
|
389
|
+
| `getBadgeCount:` completion block never called when running in an app extension, causing JS promises to hang forever in NSE handlers | iOS | Pre-existing | 9.4.0 |
|
|
390
|
+
| Notification Service Extension attachment downloads had no timeout cap (default 60-second `NSURLSession` timeout exceeds iOS's ~30-second NSE budget), causing extension process kill and notification loss on slow networks | iOS | Pre-existing | 9.4.0 |
|
|
391
|
+
| `cancelTriggerNotifications()` / `createTriggerNotification()` promises resolve before Room DB write completes, causing ~3% race on cancel-then-create patterns. Also fixes a previously-undocumented reboot-recovery data-loss bug in `NotifeeAlarmManager.rescheduleNotification` and an ordering bug in `NotificationManager.doScheduledWork` | Android | [#549](https://github.com/invertase/notifee/issues/549) | 9.5.0 |
|
|
392
|
+
| Scheduled trigger notifications silently lost across device reboot on OEM devices (Xiaomi MIUI, OnePlus, Huawei EMUI, Oppo ColorOS, Vivo FuntouchOS) whose vendor OS suppresses `BOOT_COMPLETED` until the user manually enables autostart. Also handles zombie non-repeating triggers whose fire time already passed (fire-once within a 24-hour grace period, then delete the Room row; delete silently beyond the grace period) and adds try/catch/finally guards to all notifee `BroadcastReceiver` async paths. | Android | [#734](https://github.com/invertase/notifee/issues/734) | 9.6.0 |
|
|
393
|
+
| `RepeatFrequency.DAILY` / `WEEKLY` triggers fire on day 1 but never on day 2+ (also reproduces with arrays of 24 daily reminders) — pre-fix: stale Room anchors after the post-fire repeat recalculation, plus DST ±1h shift on repeating triggers, plus reboot recovery silently dropping the rearmed PendingIntent on OEM devices that suppress `BOOT_COMPLETED` | Android | [#601](https://github.com/invertase/notifee/issues/601), [#1063](https://github.com/invertase/notifee/issues/1063) | 9.1.14 (DST + persist recalc) + 9.5.0 (await Room) + 9.6.0 (BOOT_COUNT cold-start, race guard) |
|
|
394
|
+
| Scheduled `TIMESTAMP` trigger notifications lost after device reboot on Android 14 emulator with battery optimizations off — pre-fix: `RebootBroadcastReceiver` dropped the goAsync handoff before Room writes completed; OEM devices that suppress `BOOT_COMPLETED` never re-armed the alarm at all | Android | [#991](https://github.com/invertase/notifee/issues/991) | 9.1.12 (goAsync in `RebootBroadcastReceiver`) + 9.5.0 (await Room in `rescheduleNotification`) + 9.6.0 (BOOT_COUNT cold-start for OEM suppressors) |
|
|
395
|
+
| `ObjectAlreadyConsumedException` in headless task when the same `WritableMap` is reused or the `taskConfig` accessor is read twice — `TaskConfig.init` mutated the caller's map instead of copying it first. Latent in most apps but observed in production by upstream users with high-frequency headless events | Android | [#266](https://github.com/invertase/notifee/issues/266) | 9.6.0 |
|
|
396
|
+
| `getDisplayedNotifications()` returned no `data` field on Android, breaking iOS/Android API symmetry where iOS exposes custom keys via `parseDataFromUserInfo:` (see platform limitation note below — the fix is API parity for app-posted notifications, not a workaround for FCM background auto-display) | Android | [#393](https://github.com/invertase/notifee/issues/393) | 9.7.0 |
|
|
397
|
+
| Small icon resolution failure in release builds causes `IllegalArgumentException` at `NotificationCompat.Builder.build()` — library now falls back to the app launcher icon and logs a warning instead of failing the notification display | Android | [#733](https://github.com/invertase/notifee/issues/733) | 10.1.0 |
|
|
397
398
|
|
|
398
399
|
> **Important note on `getDisplayedNotifications()` and FCM custom data on Android.**
|
|
399
400
|
>
|
|
@@ -420,11 +421,11 @@ As bugs are fixed, this table is updated. See [CHANGELOG.md](CHANGELOG.md) for f
|
|
|
420
421
|
|
|
421
422
|
Some upstream Notifee issues are not bugs in the library itself but platform-level limitations imposed by Android's Doze mode and vendor power management — no library code can make `AlarmManager` deliver an alarm to, or a foreground service survive inside, an app the OEM has explicitly paused. For these, the fork provides **documented mitigations**: user-facing helper APIs, code-level self-healing where possible, and decision guides that steer consumers toward the Android primitive most resilient to the specific vendor policy.
|
|
422
423
|
|
|
423
|
-
| Upstream issue
|
|
424
|
-
|
|
|
425
|
-
| [invertase/notifee#410](https://github.com/invertase/notifee/issues/410) | Foreground service paused on screen lock (Samsung OneUI, ~6 seconds after screen off on battery) and killed immediately when the app is backgrounded (Xiaomi MIUI)
|
|
426
|
-
| [invertase/notifee#734](https://github.com/invertase/notifee/issues/734) | Scheduled trigger notifications silently lost across a device reboot on OEM devices (Xiaomi MIUI, OnePlus, Huawei EMUI, Oppo ColorOS, Vivo FuntouchOS)
|
|
427
|
-
| [invertase/notifee#927](https://github.com/invertase/notifee/issues/927) | Custom sound passed via `displayNotification({ android: { sound, channelId }, ios: { sound } })` is ignored for **remote push notifications** (FCM/APNs) delivered while the app is in background or killed — the system default sound plays instead. Foreground delivery and **locally-scheduled notifications** (`displayNotification`, `createTriggerNotification`) are unaffected. | When a remote push arrives while the app is killed, the JavaScript layer never runs — the system tray item is drawn by the OS (Android system + Firebase SDK; iOS + APNs) before any Notifee code executes. On Android API 26+, the `NotificationChannel` sound is set once at channel creation and is immutable thereafter — `NotificationCompat.Builder.setSound()` is silently ignored when the builder has a `channelId`. On iOS, the Notification Service Extension only rewrites incoming push content when the payload contains a `notifee_options` key (see `NotifeeCoreExtensionHelper.m:43`); a plain APNs payload is delivered unmodified. | **Documentation only — the platform contract cannot be worked around at the library layer.** Recipes by platform: **(Android)** create the `NotificationChannel` with the desired sound at first-run (the channel sound is immutable; to change it the channel must be deleted and recreated under a new `channelId`), and configure `AndroidNotification.sound` in the FCM payload server-side so the system tray honors it for background pushes. As a heavier alternative, switch the backend to an FCM data-only payload and call `displayNotification()` from a headless task — the JS-side `android.sound` is then honored, but this trades simplicity for the cost of running JS on every push. **(iOS)** either set `aps.sound` directly in the APNs payload, or install the Notification Service Extension (see `docs/react-native/ios/remote-notification-support.mdx`) and ship the sound under `notifee_options.ios.sound` in the push payload.
|
|
424
|
+
| Upstream issue | Symptom | Platform root cause | Fork mitigation |
|
|
425
|
+
| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
426
|
+
| [invertase/notifee#410](https://github.com/invertase/notifee/issues/410) | Foreground service paused on screen lock (Samsung OneUI, ~6 seconds after screen off on battery) and killed immediately when the app is backgrounded (Xiaomi MIUI) | Vendor aggressive battery-saver and autostart policies suspend or terminate foreground services of apps not whitelisted in the OEM's protected-apps / autostart settings. Partially Doze-related on non-exempt `foregroundServiceType` values; mostly OEM-specific behavior catalogued at [dontkillmyapp.com](https://dontkillmyapp.com/). | **(1) Decision guide** — the [Timers: foreground service or `SET_ALARM_CLOCK`?](#timers-foreground-service-or-set_alarm_clock) section recommends the `SET_ALARM_CLOCK` trigger over a silent foreground service for rest, cooking, and recovery timer use cases. `setAlarmClock` is the same primitive the stock Clock app uses and is generally respected by vendor aggressive-kill policies. **(2) Foreground service use case matrix** — the [Foreground service use case guide](#foreground-service-use-case-guide) documents which `foregroundServiceType` values are Doze-CPU-exempt, which have type-specific timeouts, and the Google Play policy constraints that rule out misusing `mediaPlayback` for silent timers. **(3) `openPowerManagerSettings()` helper API** — points users toward known vendor autostart / protected-apps screen candidates when available; these links are best-effort because firmware variants may move, block, or remove those settings activities. |
|
|
427
|
+
| [invertase/notifee#734](https://github.com/invertase/notifee/issues/734) | Scheduled trigger notifications silently lost across a device reboot on OEM devices (Xiaomi MIUI, OnePlus, Huawei EMUI, Oppo ColorOS, Vivo FuntouchOS) | The vendor OS suppresses the `BOOT_COMPLETED` broadcast to apps the user has not manually whitelisted, so the library's `RebootBroadcastReceiver` never runs and persisted `AlarmManager` triggers are never re-armed after reboot. | **(1) `BOOT_COUNT` cold-start self-heal (code)** — on every app init, `InitProvider` compares `Settings.Global.BOOT_COUNT` against the last-known value in `SharedPreferences` and re-arms every persisted trigger on a background thread if a boot delta is detected, even when `BOOT_COMPLETED` was never delivered. Paired with a process-wide `AtomicBoolean` race guard in `NotifeeAlarmManager.rescheduleNotifications` that prevents double-advancement when the reboot receiver and the cold-start path race. **(2) `openPowerManagerSettings()` helper API** — the same vendor-settings deep-link used by #410, pointing the user at the autostart whitelist for defense in depth. |
|
|
428
|
+
| [invertase/notifee#927](https://github.com/invertase/notifee/issues/927) | Custom sound passed via `displayNotification({ android: { sound, channelId }, ios: { sound } })` is ignored for **remote push notifications** (FCM/APNs) delivered while the app is in background or killed — the system default sound plays instead. Foreground delivery and **locally-scheduled notifications** (`displayNotification`, `createTriggerNotification`) are unaffected. | When a remote push arrives while the app is killed, the JavaScript layer never runs — the system tray item is drawn by the OS (Android system + Firebase SDK; iOS + APNs) before any Notifee code executes. On Android API 26+, the `NotificationChannel` sound is set once at channel creation and is immutable thereafter — `NotificationCompat.Builder.setSound()` is silently ignored when the builder has a `channelId`. On iOS, the Notification Service Extension only rewrites incoming push content when the payload contains a `notifee_options` key (see `NotifeeCoreExtensionHelper.m:43`); a plain APNs payload is delivered unmodified. | **Documentation only — the platform contract cannot be worked around at the library layer.** Recipes by platform: **(Android)** create the `NotificationChannel` with the desired sound at first-run (the channel sound is immutable; to change it the channel must be deleted and recreated under a new `channelId`), and configure `AndroidNotification.sound` in the FCM payload server-side so the system tray honors it for background pushes. As a heavier alternative, switch the backend to an FCM data-only payload and call `displayNotification()` from a headless task — the JS-side `android.sound` is then honored, but this trades simplicity for the cost of running JS on every push. **(iOS)** either set `aps.sound` directly in the APNs payload, or install the Notification Service Extension (see `docs/react-native/ios/remote-notification-support.mdx`) and ship the sound under `notifee_options.ios.sound` in the push payload. |
|
|
428
429
|
|
|
429
430
|
Both mitigations are intentionally additive to the existing reboot-recovery and foreground-service code paths and do not replace the consumer's responsibility to prompt the user for battery-optimization exemption when the use case warrants it. For a complete vendor-by-vendor reference of autostart, battery-saver, and background-restriction behavior, see [dontkillmyapp.com](https://dontkillmyapp.com/).
|
|
430
431
|
|
|
@@ -462,10 +463,12 @@ Android 14 (API 34) requires all foreground services to declare an explicit `for
|
|
|
462
463
|
|
|
463
464
|
```xml
|
|
464
465
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
465
|
-
<!-- Replace SHORT_SERVICE with the type matching your use case -->
|
|
466
|
-
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SHORT_SERVICE" />
|
|
467
466
|
```
|
|
468
467
|
|
|
468
|
+
Some foreground service types require a matching `FOREGROUND_SERVICE_*` permission. `shortService` does not use a
|
|
469
|
+
dedicated `FOREGROUND_SERVICE_SHORT_SERVICE` permission; keep `FOREGROUND_SERVICE`, declare the service type that
|
|
470
|
+
matches your use case, and add any real type-specific permissions required by the Android platform.
|
|
471
|
+
|
|
469
472
|
2. **Declare the service type on Notifee's ForegroundService:**
|
|
470
473
|
|
|
471
474
|
```xml
|
|
@@ -485,17 +488,17 @@ Available types: `camera`, `connectedDevice`, `dataSync`, `health`, `location`,
|
|
|
485
488
|
|
|
486
489
|
Choosing the right `foregroundServiceType` matters — the wrong choice can cause Doze-driven CPU suspension with the screen off, Google Play policy rejection, or premature kills by the Android 14+ type-specific timeouts. This matrix maps common use cases to the recommended type and calls out the caveats you need to know before shipping:
|
|
487
490
|
|
|
488
|
-
| Use case
|
|
489
|
-
|
|
|
490
|
-
| Silent rest / workout / cooking timer
|
|
491
|
-
| Timer with audio cue (metronome, guided set) | `mediaPlayback`
|
|
492
|
-
| Short operation (< 3 min)
|
|
493
|
-
| Long-running data sync
|
|
494
|
-
| Location / navigation / fitness GPS
|
|
495
|
-
| Music / podcast / audiobook playback
|
|
496
|
-
| Bluetooth / USB device sync
|
|
497
|
-
| Enterprise / DPC / system-critical
|
|
498
|
-
| Arbitrary deferrable background work
|
|
491
|
+
| Use case | Recommended type | Doze CPU exempt? | Type timeout | Key caveat |
|
|
492
|
+
| -------------------------------------------- | -------------------------------------------------- | ---------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
493
|
+
| Silent rest / workout / cooking timer | **`SET_ALARM_CLOCK` trigger — not an FGS** | N/A | N/A | See the ["Timers: foreground service or `SET_ALARM_CLOCK`?"](#timers-foreground-service-or-set_alarm_clock) decision guide below. |
|
|
494
|
+
| Timer with audio cue (metronome, guided set) | `mediaPlayback` | Yes | None | Must actually play audio — silent `mediaPlayback` is a Play Store policy violation. |
|
|
495
|
+
| Short operation (< 3 min) | `shortService` | No | **3 min** | Library's `onTimeout()` stops cleanly and emits `TYPE_FG_TIMEOUT` to JS. |
|
|
496
|
+
| Long-running data sync | `dataSync` | No | 6 h (API 34); stricter on API 35+ | Pair with `openBatteryOptimizationSettings()` for reliability on OEM devices. |
|
|
497
|
+
| Location / navigation / fitness GPS | `location` | Yes | None | Requires `ACCESS_FINE_LOCATION` runtime permission. |
|
|
498
|
+
| Music / podcast / audiobook playback | `mediaPlayback` | Yes | None | Must be real playback — see policy callout below. |
|
|
499
|
+
| Bluetooth / USB device sync | `connectedDevice` | No | None | Requires companion-device or Bluetooth permission. |
|
|
500
|
+
| Enterprise / DPC / system-critical | `specialUse` or `systemExempted` | Varies | None | `specialUse` requires a `<property>` element and Play Store justification review. |
|
|
501
|
+
| Arbitrary deferrable background work | **None — use `WorkManager` directly, not an FGS.** | N/A | N/A | FGS is not the right abstraction for deferrable work. |
|
|
499
502
|
|
|
500
503
|
> **Warning:** **`mediaPlayback` requires active audio playback.** [Google Play's Foreground Service Types policy](https://support.google.com/googleplay/android-developer/answer/13392821) explicitly prohibits declaring `mediaPlayback` for services that do not play audio. A silent timer, stopwatch, or rest-timer declared as `mediaPlayback` will be rejected during Play Store review. For silent long-running timers, prefer the `SET_ALARM_CLOCK` trigger path (see the decision guide below).
|
|
501
504
|
|
|
@@ -523,7 +526,7 @@ The fork mitigates this with two layers that work together:
|
|
|
523
526
|
|
|
524
527
|
**1. Automatic cold-start recovery.** On every app init, the library compares `Settings.Global.BOOT_COUNT` against the value recorded on the previous run. If a reboot has occurred since the last run — whether or not `BOOT_COMPLETED` was delivered to your app — the library re-arms every persisted trigger on a background thread. This means that on an OEM device where `BOOT_COMPLETED` was suppressed, simply opening your app (or having it cold-started by any other entry point: push notification, geofence, share intent) recovers all missed and upcoming alarms. Previously, opening the app alone did not recover them. This recovery runs unconditionally — it is not gated by the `notifee_init_warmup_enabled` metadata flag, because it is a correctness fix rather than a startup optimization.
|
|
525
528
|
|
|
526
|
-
**2. Vendor settings helper APIs.** The existing `getPowerManagerInfo()` and `openPowerManagerSettings()` APIs let your app guide the user
|
|
529
|
+
**2. Vendor settings helper APIs.** The existing `getPowerManagerInfo()` and `openPowerManagerSettings()` APIs let your app guide the user toward known vendor settings candidates (Xiaomi Autostart, Huawei Protected Apps, Oppo Startup Manager, and 13 more vendors) to whitelist the app. These candidates are opened best-effort: Android may reject or fail to resolve a vendor-specific settings activity on some firmware variants, and the helper fails safely instead of crashing. Consumer apps do not need to inherit package-visibility `<queries>` declarations for these helpers, and the helper does not use the direct `ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` request path. Whitelisting the app in vendor settings can restore normal reboot delivery and reduce background foreground-service kills on affected devices, but this remains subject to OEM firmware and user/device policy — so this helper is a mitigation path for **both** trigger-notification reliability and foreground-service reliability on OEM devices.
|
|
527
530
|
|
|
528
531
|
A typical integration that combines both layers looks like this:
|
|
529
532
|
|
|
@@ -552,9 +555,9 @@ if (Platform.OS === 'android') {
|
|
|
552
555
|
|
|
553
556
|
For the authoritative vendor-by-vendor matrix of autostart, battery optimization, and background-restriction behavior, see [dontkillmyapp.com](https://dontkillmyapp.com/).
|
|
554
557
|
|
|
555
|
-
> **Scope note:** the cold-start recovery path is best-effort. It runs as soon as Android invokes `InitProvider.onCreate` (before `Application.onCreate`), but may still be delayed by minutes or hours on a device where the user never opens your app after a reboot. For use cases that require guaranteed sub-second timing (alarm clocks,
|
|
558
|
+
> **Scope note:** the cold-start recovery path is best-effort. It runs as soon as Android invokes `InitProvider.onCreate` (before `Application.onCreate`), but may still be delayed by minutes or hours on a device where the user never opens your app after a reboot. For use cases that require guaranteed sub-second timing (alarm clocks, time-sensitive reminders, calendar events), also declare `USE_EXACT_ALARM` in your manifest (see the [note above](#bugs-fixed-from-upstream-notifee)) and prompt the user to whitelist your app via the vendor settings helper.
|
|
556
559
|
>
|
|
557
|
-
> **Defense in depth:** the cold-start BOOT_COUNT path and the traditional `RebootBroadcastReceiver` path both funnel into the same `NotifeeAlarmManager.rescheduleNotifications` entry point, which is guarded by a process-wide `AtomicBoolean` — whichever path runs first wins the reschedule cycle, and the second logs `Reschedule already in progress, skipping duplicate request` and exits cleanly. On real devices the two paths often
|
|
560
|
+
> **Defense in depth:** the cold-start `BOOT_COUNT` path and the traditional `RebootBroadcastReceiver` path both funnel into the same `NotifeeAlarmManager.rescheduleNotifications` entry point, which is guarded by a process-wide `AtomicBoolean` — whichever path runs first wins the reschedule cycle, and the second logs `Reschedule already in progress, skipping duplicate request` and exits cleanly. On real devices the two paths often _both_ fire, for a subtle reason observed during Step 6 smoke testing: when the system force-stops your app (during an install, crash recovery, or a `pm clear` from a QA tool) and then Android re-delivers `BOOT_COMPLETED` as soon as the package is launched again, the reboot receiver runs at the same time as `InitProvider.onCreate`'s cold-start check. You get both paths for free — proof of the race guard's design. On an OEM device that suppresses `BOOT_COMPLETED` outright, only the cold-start path runs. Either way the zombie re-fire loop is broken.
|
|
558
561
|
|
|
559
562
|
### Trigger Notification Reliability
|
|
560
563
|
|
|
@@ -584,13 +587,13 @@ five `AlarmType` values — including `SET_ALARM_CLOCK`, which upstream Notifee
|
|
|
584
587
|
[invertase/notifee#655](https://github.com/invertase/notifee/issues/655) and merged via
|
|
585
588
|
[#749](https://github.com/invertase/notifee/pull/749).
|
|
586
589
|
|
|
587
|
-
| AlarmType
|
|
588
|
-
|
|
|
589
|
-
| `SET`
|
|
590
|
-
| `SET_AND_ALLOW_WHILE_IDLE`
|
|
591
|
-
| `SET_EXACT`
|
|
592
|
-
| `SET_EXACT_AND_ALLOW_WHILE_IDLE`
|
|
593
|
-
| `SET_ALARM_CLOCK`
|
|
590
|
+
| AlarmType | Exact? | Wakes device? | Doze bypass? | Status bar icon | When to use |
|
|
591
|
+
| -------------------------------- | ------ | ------------- | ------------ | --------------- | ------------------------------------------------------------------------------ |
|
|
592
|
+
| `SET` | No | Yes | No | No | Non-critical reminders that can slip by several minutes (daily digest). |
|
|
593
|
+
| `SET_AND_ALLOW_WHILE_IDLE` | No | Yes | Yes | No | Non-critical reminders that must still fire while the device is in Doze. |
|
|
594
|
+
| `SET_EXACT` | Yes | Yes | No | No | Time-sensitive reminders when the app is reasonably sure not to be in Doze. |
|
|
595
|
+
| `SET_EXACT_AND_ALLOW_WHILE_IDLE` | Yes | Yes | Yes | No | **Fork default.** Time-sensitive reminders that must fire even in Doze. |
|
|
596
|
+
| `SET_ALARM_CLOCK` | Yes | Yes | Yes | **Yes** | True alarm-clock / recovery-timer use cases — highest priority, OEM-resilient. |
|
|
594
597
|
|
|
595
598
|
`SET_ALARM_CLOCK` is the strongest Android guarantee available for a scheduled notification:
|
|
596
599
|
|
|
@@ -602,7 +605,7 @@ five `AlarmType` values — including `SET_ALARM_CLOCK`, which upstream Notifee
|
|
|
602
605
|
`setAlarmClock` even when they would otherwise drop `setExactAndAllowWhileIdle`. This is the
|
|
603
606
|
same mechanism the stock Clock app uses.
|
|
604
607
|
- **Intended for the same reliability problem as [invertase/notifee#734](https://github.com/invertase/notifee/issues/734).**
|
|
605
|
-
If your use case is a
|
|
608
|
+
If your use case is a time-sensitive reminder, a rest-timer between gym sets, a cooking timer,
|
|
606
609
|
or any recovery-timer scenario where a missed notification is user-visible damage, prefer
|
|
607
610
|
`SET_ALARM_CLOCK` over the fork default.
|
|
608
611
|
|
|
@@ -636,13 +639,13 @@ and consider prompting the user with `openAlarmPermissionSettings()`.
|
|
|
636
639
|
|
|
637
640
|
A common question for this fork: **should a rest / cooking / recovery timer be a foreground service, or a scheduled trigger notification?** For most timer use cases the answer is the trigger path — and specifically `SET_ALARM_CLOCK`.
|
|
638
641
|
|
|
639
|
-
| Timer characteristic
|
|
640
|
-
|
|
|
641
|
-
| Fires once at a known time, no live UI update while app is backgrounded | **`SET_ALARM_CLOCK` trigger** (see [AlarmType guide](#alarmtype-guide))
|
|
642
|
-
| Fires repeatedly at known intervals
|
|
643
|
-
| Needs a live ticking notification UI while app is backgrounded
|
|
644
|
-
| Streams audio, music, or guided voice
|
|
645
|
-
| Continuous background work (location, Bluetooth)
|
|
642
|
+
| Timer characteristic | Recommended approach |
|
|
643
|
+
| ----------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
644
|
+
| Fires once at a known time, no live UI update while app is backgrounded | **`SET_ALARM_CLOCK` trigger** (see [AlarmType guide](#alarmtype-guide)) |
|
|
645
|
+
| Fires repeatedly at known intervals | **`SET_ALARM_CLOCK` trigger** with app-side scheduling of the next cycle |
|
|
646
|
+
| Needs a live ticking notification UI while app is backgrounded | Foreground service (`mediaPlayback` if audio, otherwise reconsider the UX) |
|
|
647
|
+
| Streams audio, music, or guided voice | Foreground service with `mediaPlayback` |
|
|
648
|
+
| Continuous background work (location, Bluetooth) | Foreground service with the matching type from the matrix above |
|
|
646
649
|
|
|
647
650
|
**Why `SET_ALARM_CLOCK` is usually the right choice for timers:**
|
|
648
651
|
|
|
@@ -651,7 +654,7 @@ A common question for this fork: **should a rest / cooking / recovery timer be a
|
|
|
651
654
|
- **No risk of Play Store rejection** for misusing `mediaPlayback` on a silent timer.
|
|
652
655
|
- **No wake lock to manage.** The library's foreground-service path does not acquire a wake lock on your behalf — under Doze on a non-exempt `foregroundServiceType`, the CPU can still suspend with the screen off. `SET_ALARM_CLOCK` wakes the device at fire time regardless of Doze state.
|
|
653
656
|
|
|
654
|
-
**When a foreground service
|
|
657
|
+
**When a foreground service _is_ the right choice:**
|
|
655
658
|
|
|
656
659
|
- You need the notification to tick every second while the app is backgrounded (metronome with audio, VoIP call, active GPS track). A `SET_ALARM_CLOCK` trigger fires once at the scheduled time, not continuously.
|
|
657
660
|
- You need actual audio playback — use `mediaPlayback`.
|
|
@@ -747,7 +750,7 @@ The fix is to set the sound in the push payload **server-side**:
|
|
|
747
750
|
|
|
748
751
|
An advanced alternative on Android is to switch the backend to an FCM **data-only** payload and call `notifee.displayNotification()` from a headless task — this lets the JS-side `android.sound` win, at the cost of running JS on every push. Most apps should prefer the server-side payload approach.
|
|
749
752
|
|
|
750
|
-
**Local notifications are different.** This limitation only affects **remote pushes** delivered by FCM/APNs while the app is killed. Notifications scheduled locally via `notifee.displayNotification()` or `notifee.createTriggerNotification()` — for example, a timer firing after the user closed the app —
|
|
753
|
+
**Local notifications are different.** This limitation only affects **remote pushes** delivered by FCM/APNs while the app is killed. Notifications scheduled locally via `notifee.displayNotification()` or `notifee.createTriggerNotification()` — for example, a timer firing after the user closed the app — _do_ honor the JS-side `sound` parameter, because the library itself wakes up and presents the notification (via `AlarmManager` on Android or `UNUserNotificationCenter` on iOS). The usual platform rules still apply: on Android the `NotificationChannel` sound is immutable after creation and wins over the per-notification `sound`; on iOS the sound file must be bundled in the app (`.wav`/`.aiff`/`.caf`, under 30 seconds, in the main bundle). For reliable local timer notifications on OEM devices that aggressively kill background work, prefer `AlarmType.SET_ALARM_CLOCK` — see the [Timers: foreground service or `SET_ALARM_CLOCK`?](#timers-foreground-service-or-set_alarm_clock) section.
|
|
751
754
|
|
|
752
755
|
Reference: [invertase/notifee#927](https://github.com/invertase/notifee/issues/927).
|
|
753
756
|
|
|
@@ -831,31 +834,31 @@ The full `react-native-notify-kit` documentation is hosted on docs.page and is k
|
|
|
831
834
|
|
|
832
835
|
The APIs for Android allow for creating rich, styled and highly interactive notifications. Below you'll find guides that cover the supported Android features.
|
|
833
836
|
|
|
834
|
-
| Topic
|
|
835
|
-
|
|
|
836
|
-
| [Appearance](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/appearance)
|
|
837
|
-
| [Behaviour](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/behaviour)
|
|
838
|
-
| [Channels & Groups](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/channels)
|
|
839
|
-
| [Foreground Service](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/foreground-service)
|
|
840
|
-
| [Grouping & Sorting](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/grouping-and-sorting) | Group and sort related notifications in a single notification pane.
|
|
841
|
-
| [Interaction](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/interaction)
|
|
842
|
-
| [Progress Indicators](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/progress-indicators) | Show users a progress indicator of an on-going background task, and learn how to keep it updated.
|
|
843
|
-
| [Styles](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/styles)
|
|
844
|
-
| [Timers](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/timers)
|
|
837
|
+
| Topic | |
|
|
838
|
+
| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
839
|
+
| [Appearance](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/appearance) | Change the appearance of a notification; icons, colors, visibility etc. |
|
|
840
|
+
| [Behaviour](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/behaviour) | Customize how a notification behaves when it is delivered to a device; sound, vibration, lights etc. |
|
|
841
|
+
| [Channels & Groups](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/channels) | Organize your notifications into channels & groups to allow users to control how notifications are handled on their device. |
|
|
842
|
+
| [Foreground Service](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/foreground-service) | Long running background tasks can take advantage of an Android Foreground Service to display an on-going, prominent notification. |
|
|
843
|
+
| [Grouping & Sorting](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/grouping-and-sorting) | Group and sort related notifications in a single notification pane. |
|
|
844
|
+
| [Interaction](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/interaction) | Allow users to interact with your application directly from the notification, with actions. |
|
|
845
|
+
| [Progress Indicators](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/progress-indicators) | Show users a progress indicator of an on-going background task, and learn how to keep it updated. |
|
|
846
|
+
| [Styles](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/styles) | Style notifications to show richer content, such as expandable images/text, or message conversations. |
|
|
847
|
+
| [Timers](https://docs.page/marcocrupi/react-native-notify-kit/react-native/android/timers) | Display counting timers on your notification, useful for on-going tasks such as a phone call, or event time remaining. |
|
|
845
848
|
|
|
846
849
|
### iOS
|
|
847
850
|
|
|
848
851
|
Below you'll find guides that cover the supported iOS features.
|
|
849
852
|
|
|
850
|
-
| Topic
|
|
851
|
-
|
|
|
852
|
-
| [Appearance](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/appearance)
|
|
853
|
-
| [Badges](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/badges)
|
|
854
|
-
| [Behaviour](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/behaviour)
|
|
855
|
-
| [Categories](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/categories)
|
|
856
|
-
| [Interaction](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/interaction)
|
|
857
|
-
| [Permissions](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/permissions)
|
|
858
|
-
| [Remote Notification Support](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/remote-notification-support) | Handle and display remote notifications with Notification Service Extension.
|
|
853
|
+
| Topic | |
|
|
854
|
+
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
855
|
+
| [Appearance](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/appearance) | Change how the notification is displayed to your users. |
|
|
856
|
+
| [Badges](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/badges) | Manage the app icon badge count on iOS devices. |
|
|
857
|
+
| [Behaviour](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/behaviour) | Control how notifications behave when they are displayed on a device; sound, critical alerts, etc. |
|
|
858
|
+
| [Categories](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/categories) | Create & assign categories to notifications. |
|
|
859
|
+
| [Interaction](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/interaction) | Handle user interaction with your notifications. |
|
|
860
|
+
| [Permissions](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/permissions) | Request permission from your application users to display notifications. |
|
|
861
|
+
| [Remote Notification Support](https://docs.page/marcocrupi/react-native-notify-kit/react-native/ios/remote-notification-support) | Handle and display remote notifications with Notification Service Extension. |
|
|
859
862
|
|
|
860
863
|
## Trademark Notice
|
|
861
864
|
|
package/android/build.gradle
CHANGED
|
@@ -53,7 +53,7 @@ android {
|
|
|
53
53
|
defaultConfig {
|
|
54
54
|
minSdk = 24
|
|
55
55
|
targetSdk = 35
|
|
56
|
-
multiDexEnabled true
|
|
56
|
+
multiDexEnabled = true
|
|
57
57
|
|
|
58
58
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
59
59
|
|
|
@@ -66,7 +66,7 @@ android {
|
|
|
66
66
|
|
|
67
67
|
lint {
|
|
68
68
|
disable 'GradleCompatible'
|
|
69
|
-
abortOnError false
|
|
69
|
+
abortOnError = false
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
compileOptions {
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
9
9
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
10
10
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
|
11
|
-
<uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" android:maxSdkVersion="30" />
|
|
12
11
|
<!-- For Xiaomi devices to enable heads-up notifications as default (https://github.com/invertase/notifee/issues/296) -->
|
|
13
12
|
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" android:minSdkVersion="23" />
|
|
14
13
|
|
|
@@ -415,6 +415,7 @@ public class ForegroundService extends Service {
|
|
|
415
415
|
* @return the raw {@code foregroundServiceType} bitmask from the manifest, or 0 if the service is
|
|
416
416
|
* not declared or has no explicit type
|
|
417
417
|
*/
|
|
418
|
+
@RequiresApi(Build.VERSION_CODES.Q)
|
|
418
419
|
private int getDeclaredForegroundServiceType() {
|
|
419
420
|
try {
|
|
420
421
|
ComponentName component = new ComponentName(this, ForegroundService.class);
|
|
@@ -23,10 +23,12 @@ import static app.notifee.core.event.NotificationEvent.TYPE_ACTION_PRESS;
|
|
|
23
23
|
import static app.notifee.core.event.NotificationEvent.TYPE_PRESS;
|
|
24
24
|
import static java.lang.Integer.parseInt;
|
|
25
25
|
|
|
26
|
+
import android.Manifest;
|
|
26
27
|
import android.app.Notification;
|
|
27
28
|
import android.app.PendingIntent;
|
|
28
29
|
import android.content.Context;
|
|
29
30
|
import android.content.Intent;
|
|
31
|
+
import android.content.pm.PackageManager;
|
|
30
32
|
import android.graphics.Bitmap;
|
|
31
33
|
import android.net.Uri;
|
|
32
34
|
import android.os.Build;
|
|
@@ -248,9 +250,7 @@ class NotificationManager {
|
|
|
248
250
|
|
|
249
251
|
builder.setColorized(androidModel.getColorized());
|
|
250
252
|
|
|
251
|
-
|
|
252
|
-
builder.setChronometerCountDown(androidModel.getChronometerCountDown());
|
|
253
|
-
}
|
|
253
|
+
builder.setChronometerCountDown(androidModel.getChronometerCountDown());
|
|
254
254
|
|
|
255
255
|
if (androidModel.getGroup() != null) {
|
|
256
256
|
builder.setGroup(androidModel.getGroup());
|
|
@@ -716,7 +716,18 @@ class NotificationManager {
|
|
|
716
716
|
Trace.endSection();
|
|
717
717
|
}
|
|
718
718
|
} else {
|
|
719
|
-
|
|
719
|
+
Context context = getApplicationContext();
|
|
720
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
|
|
721
|
+
&& context.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS)
|
|
722
|
+
!= PackageManager.PERMISSION_GRANTED) {
|
|
723
|
+
String message =
|
|
724
|
+
"POST_NOTIFICATIONS permission is not granted. Notification was not"
|
|
725
|
+
+ " displayed.";
|
|
726
|
+
Logger.w(TAG, message);
|
|
727
|
+
return Futures.immediateFailedFuture(new SecurityException(message));
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
NotificationManagerCompat.from(context)
|
|
720
731
|
.notify(androidBundle.getTag(), hashCode, notification);
|
|
721
732
|
}
|
|
722
733
|
|
|
@@ -818,6 +829,12 @@ class NotificationManager {
|
|
|
818
829
|
Boolean withAlarmManager = trigger.getWithAlarmManager();
|
|
819
830
|
Context context = getApplicationContext();
|
|
820
831
|
|
|
832
|
+
if (!withAlarmManager && TimestampTriggerModel.MONTHLY.equals(trigger.getRepeatFrequency())) {
|
|
833
|
+
String message = "RepeatFrequency.MONTHLY is not supported without AlarmManager.";
|
|
834
|
+
Logger.e(TAG, message);
|
|
835
|
+
return Futures.immediateFailedFuture(new IllegalArgumentException(message));
|
|
836
|
+
}
|
|
837
|
+
|
|
821
838
|
ListenableFuture<Void> insertFuture =
|
|
822
839
|
WorkDataRepository.insertTriggerNotification(
|
|
823
840
|
context, notificationModel, triggerBundle, withAlarmManager);
|
|
@@ -867,10 +884,6 @@ class NotificationManager {
|
|
|
867
884
|
() -> {
|
|
868
885
|
List<Bundle> notifications = new ArrayList<Bundle>();
|
|
869
886
|
|
|
870
|
-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
871
|
-
return notifications;
|
|
872
|
-
}
|
|
873
|
-
|
|
874
887
|
android.app.NotificationManager notificationManager =
|
|
875
888
|
(android.app.NotificationManager)
|
|
876
889
|
getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
|
@@ -27,9 +27,25 @@ import android.content.Intent;
|
|
|
27
27
|
*/
|
|
28
28
|
public class RebootBroadcastReceiver extends BroadcastReceiver {
|
|
29
29
|
private static final String TAG = "RebootReceiver";
|
|
30
|
+
private static final String ACTION_QUICKBOOT_POWERON = "android.intent.action.QUICKBOOT_POWERON";
|
|
31
|
+
private static final String ACTION_HTC_QUICKBOOT_POWERON =
|
|
32
|
+
"com.htc.intent.action.QUICKBOOT_POWERON";
|
|
30
33
|
|
|
31
34
|
@Override
|
|
32
35
|
public void onReceive(Context context, Intent intent) {
|
|
36
|
+
if (intent == null) {
|
|
37
|
+
Logger.w(TAG, "Ignoring reboot event with null intent");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
String action = intent.getAction();
|
|
42
|
+
if (!Intent.ACTION_BOOT_COMPLETED.equals(action)
|
|
43
|
+
&& !ACTION_QUICKBOOT_POWERON.equals(action)
|
|
44
|
+
&& !ACTION_HTC_QUICKBOOT_POWERON.equals(action)) {
|
|
45
|
+
Logger.w(TAG, "Ignoring unsupported reboot event action: " + action);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
33
49
|
PendingResult pendingResult = goAsync();
|
|
34
50
|
// Tracks whether the synchronous section successfully handed off to the
|
|
35
51
|
// async reschedule path. If not, the finally block must call finish() to
|