Skip to content

[FCE-3499] Android FCM coexistence, relay non-VoIP pushes and tokens to the app's other notification library#564

Draft
Magmusacy wants to merge 1 commit into
FCE-3435from
FCE-3599
Draft

[FCE-3499] Android FCM coexistence, relay non-VoIP pushes and tokens to the app's other notification library#564
Magmusacy wants to merge 1 commit into
FCE-3435from
FCE-3599

Conversation

@Magmusacy

Copy link
Copy Markdown
Collaborator

Description

Android delivers each FCM message to exactly one MESSAGING_EVENT service per app, so
our VoIP PushNotificationService used to swallow every push — apps also using
expo-notifications or @react-native-firebase/messaging silently lost all their
notifications and token callbacks (repro'd on baseline: builds clean, expo receives
nothing).

This PR makes the two coexist:

  • Explicit payload discriminator — a data message is a call iff it carries
    fishjam: "voip-incoming" (namespaced key, typed value so future kinds like a cancel
    push fit the same key). The example server now sends it.
  • Native relay — non-VoIP messages, token callbacks (onNewToken + onRegistered),
    and onDeletedMessages are handed to the app's other messaging service, configured via
    VoipFallbackMessagingService manifest meta-data. The fallback class is instantiated
    reflectively (attachBaseContext injected, same pattern Braze uses in production), so
    its real native code runs — killed-state behavior preserved, no JS required.
  • Config plugin — new android.voipFallbackMessagingService option
    ("expo-notifications", "@react-native-firebase/messaging", or a class name):
    writes the meta-data, strips the library's own service with tools:node="remove",
    and gives ours android:priority="1". New android.voipMessagingService: false
    opt-out for apps bringing their own dispatcher.
  • Escape hatch — public PushNotificationService.handleVoipMessage(context, message): Boolean / handleNewToken(token) for apps that own their messaging service.

Motivation and Context

A host app cannot currently use any other push-notification library alongside Fishjam
VoIP on Android: our service claims the single FCM slot and drops everything that isn't a
call — with no error anywhere (the manifest merges fine; expo-notifications even ships its
service at priority −1, so ours always wins and theirs is dead code). This is a hard
blocker for real apps, which virtually always have non-VoIP notifications.

Documentation impact

  • Documentation update required
  • Documentation updated in another PR
  • No documentation update required

(README §9.6 "Coexisting with other push-notification libraries" — setup, wire format,
bare-RN recipe, dispatcher example — is included in this PR.)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to
    not work as expected)

✅ Runtime-tested (Pixel 9 emulator, real FCM v1 sends, expo-notifications 0.32.17 as fallback)

Test Result
Merged manifest / dumpsys: our service sole MESSAGING_EVENT handler, expo's removed
Token relay → expo's onNewToken (its token listeners keep working)
Non-VoIP push → relayed → expo JS listener received full payload (25 ms e2e)
Non-VoIP push, app killed (pidof empty) → native relay, expo shows notification
VoIP push (fishjam: "voip-incoming") rings in fg / bg / killed
Foreign payload containing roomName but no/wrong fishjam key → relayed, no phantom call
Baseline (no relay) + expo-notifications: builds fine, but expo silently receives nothing — the bug this PR fixes ✅ repro'd

@linear

linear Bot commented Jul 17, 2026

Copy link
Copy Markdown

FCE-3499

FCE-3599

@Magmusacy
Magmusacy changed the base branch from main to FCE-3435 July 17, 2026 21:17
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