Skip to content

feat(android): report full-screen intent availability in getNotificationSettings - #65

Open
KAMRONBEK wants to merge 1 commit into
marcocrupi:devfrom
KAMRONBEK:feat/full-screen-intent-setting
Open

feat(android): report full-screen intent availability in getNotificationSettings#65
KAMRONBEK wants to merge 1 commit into
marcocrupi:devfrom
KAMRONBEK:feat/full-screen-intent-setting

Conversation

@KAMRONBEK

Copy link
Copy Markdown
Contributor

Closes #64.

What

Adds android.fullScreenIntent to getNotificationSettings(), an AndroidNotificationSetting reporting whether a notification posted with a fullScreenAction will actually be shown full screen.

Why

Android 14 / API 34 turned USE_FULL_SCREEN_INTENT into a user-revocable special app access: the Play Store revokes it on install for apps outside the calling and alarm categories, apps installed before the device upgraded keep it, and the user can toggle it at any time under Settings → Apps → Special app access.

A denial is completely silent. The notification still posts, the promise resolves, nothing throws — only the full-screen presentation is dropped. None of the signals available to JS help:

  • Build.VERSION.SDK_INT — the state is per-app and per-user, not per-OS-version.
  • The manifest permission — dumpsys package still reports granted=true while the app-op denies it.
  • getNotificationSettings() — reports authorizationStatus and android.alarm, both of which stay green.

The only reliable signal is NotificationManager.canUseFullScreenIntent(), which has no binding here and cannot be added from JS. A calling app is left ringing without ever taking the lock screen, unable to explain why or offer the one-tap fix.

Shape

Deliberately modelled on the existing alarmAlarmManager.canScheduleExactAlarms() field — one boolean special-access check, one AndroidNotificationSetting, no new method on the public API surface:

Condition Value
API < 34 ENABLED — granted at install, always honoured
API ≥ 34, canUseFullScreenIntent() true ENABLED
API ≥ 34, canUseFullScreenIntent() false DISABLED
iOS / web ENABLED — the same fallback alarm already uses

FullScreenIntentUtils.canUseFullScreenIntent() fails open when the NotificationManager is unavailable: a state we cannot prove is not one apps should nag the user about.

Scope

Detection only. I left out an openFullScreenIntentSettings() companion to openAlarmPermissionSettings() on purpose — launching Settings.ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT is already possible from JS with any intent launcher, so it isn't a gap. Detection is the part JS cannot do. Happy to add it in a follow-up if you'd like the pair symmetric.

Why this touches the core

packages/react-native/android/.../Notifee.java is the only place the value can come from — it's behind a native NotificationManager call, so the bridge layer can't reach it. Per CONTRIBUTING.md ("Modifications to the core are therefore fully allowed when the bridge layer isn't the right place"), flagging explicitly since the issue template still says the core isn't modified. The change is 9 lines in getNotificationSettings, immediately beside the alarm block it mirrors, plus one new utility.

Changes

File
utility/FullScreenIntentUtils.java new — SDK-gated check, mirroring AlarmUtils.canScheduleExactAlarms()
Notifee.java writes fullScreenIntent into the android settings bundle
utility/FullScreenIntentUtilsTest.java new — 5 Robolectric cases across the API boundary
types/NotificationAndroid.ts the new field + JSDoc
NotifeeApiModule.ts all four iOS/web fallback construction sites (requestPermission ×2, getNotificationSettings ×2)
jest-mock.js testNotificationSettings fixture
__tests__/NotifeeApiModule.test.ts updated assertions + a new pass-through case for a denied grant
CHANGELOG.md [Unreleased] → Added

Verification

Run on Windows, Node 22.20.0, JDK 17:

  • yarn tests_rn:test654 passed, 38 suites, including the new case
  • ./gradlew :react-native-notify-kit:testDebugUnitTest — the new suite reports tests="5" skipped="0" failures="0" errors="0"
  • yarn validate:all:ts — clean
  • Prettier — clean on every file touched

One thing to flag so it isn't mistaken for my change: in my Windows environment 14 of the 15 tests in NotifeeAlarmManagerCurrentBehaviorTest fail with IllegalStateException: Illegal connection pointer (Room/SQLite under Robolectric), which turns the whole Gradle task red. I re-ran that suite on a clean dev checkout with no changes applied and got the identical 14/15, so it is environmental and pre-existing rather than anything this PR touches. Every other suite is green.

On device: not verified for this PR, and I want to be straight about that. The identical native logic has been shipping in a production Android calling app via patch-package, which is where the problem was found and diagnosed (the tell was a missing fullscreenIntent= line in dumpsys notification while dumpsys package still showed the permission granted). But the full grant → revoke → re-read cycle on an API 34 device was not re-run against this branch — the coverage here is the Robolectric matrix pinning both sides of the API boundary. Glad to do a device pass if you'd like one before merging.

One note: I did not regenerate docs/react-native/reference/ — typedoc output carries source line-number links, so it churns unrelated files. Say the word and I'll run yarn gen:reference here instead of leaving it to the release.

…ionSettings

Android 14 / API 34 turned USE_FULL_SCREEN_INTENT into a user-revocable
special app access: the Play Store revokes it on install for apps outside
the calling and alarm categories, apps installed before the device upgraded
keep it, and the user can toggle it at any time.

A denial is silent. The notification still posts, the promise resolves and
nothing throws — only the full screen presentation is dropped. Neither
Build.VERSION.SDK_INT nor the manifest permission is a usable signal, so
apps had no way to explain the behaviour or offer the fix.

Expose it as android.fullScreenIntent on getNotificationSettings(), beside
the existing android.alarm field and with the same semantics: ENABLED below
API 34, and NotificationManager.canUseFullScreenIntent() at or above it.
The check fails open when the NotificationManager is unavailable, so a state
we cannot prove never has apps nag the user.

Closes marcocrupi#64
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant