feat: Add Android push notification support to Expo config plugin#381
Closed
Rosie-Kennelly-1 wants to merge 8 commits intomainfrom
Closed
feat: Add Android push notification support to Expo config plugin#381Rosie-Kennelly-1 wants to merge 8 commits intomainfrom
Rosie-Kennelly-1 wants to merge 8 commits intomainfrom
Conversation
The Expo config plugin already automated iOS push notification setup (PR #191) but Android was left out, requiring developers to manually create a FirebaseMessagingService and edit native files — defeating the purpose of using Expo. This adds the Android counterpart: a config plugin that generates a Kotlin FirebaseMessagingService at prebuild time, registers it in the AndroidManifest, and routes Intercom pushes to the SDK while passing non-Intercom messages through to other handlers (e.g. expo-notifications). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add explicit android:priority="10" on intent filter - Add utf-8 encoding to writeFileSync for generated Kotlin source - Add test for preserving pre-existing services in AndroidManifest - Exclude __tests__ from tsconfig to match existing JS test convention - Remove unnecessary comments Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
If a developer already has a FirebaseMessagingService registered (from manual setup or another SDK), adding a second one would cause unpredictable FCM routing. The plugin now detects this and skips registration with a warning explaining how to route Intercom pushes manually. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Apply prettier formatting fixes - Exclude __tests__ from tsconfig.build.json so bob build doesn't try to generate type definitions for test files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The native module declares firebase-messaging as an `implementation` dependency, which is private to the library module. Since the generated FirebaseMessagingService lives in the app module, it needs firebase-messaging on its own compile classpath. Conditionally adds the dependency to app/build.gradle if not already present. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ild time Instead of hardcoding the firebase-messaging version, read it from the native module's android/build.gradle so the app dependency stays in sync automatically when the SDK is updated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
__dirname resolves differently from src/ vs lib/commonjs/ after compilation. Using require.resolve to find the package.json ensures the native module's android/build.gradle is found correctly regardless of the build output directory structure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
|
Superseded by a stacked PR series for easier review:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why?
The Expo config plugin automates iOS push notification setup (since PR #191) but has no Android equivalent. This means Expo developers' end users silently never receive push notifications on Android when a support agent replies to their conversation — and the only workaround is manually creating native Kotlin files, which defeats the purpose of using Expo.
How?
A new config plugin generates a Kotlin
FirebaseMessagingServiceatexpo prebuildtime and registers it inAndroidManifest.xml, following the exact pattern already proven in thewith-notificationsexample. The service routes Intercom pushes to the SDK and passes non-Intercom messages through for other handlers (e.g.expo-notifications). The plugin also conditionally addsfirebase-messagingto the app module'sbuild.gradlewhen not already present — needed because the native module declares it asimplementation(private to the library), but the generated service in the app module requires it on its compile classpath.Also fixes a pre-existing bug in
withPushNotifications.tswhereconfigwas passed instead ofnewConfigtoappDelegateandinfoPlist, breaking the plugin chaining.Decisions
@intercom/intercom-react-nativeis in your Expo plugins.android:exported="false"on the service — more secure than the"true"used in thewith-notificationsexample. Firebase delivers messages internally; the service doesn't need to be externally accessible.android:priority="10"on the intent filter — explicitly ensures Intercom's service handles FCM events before lower-priority services likeexpo-notifications(which registers at-1).firebase-messaging:24.1.2is added to the app'sbuild.gradleonly if not already present. The native module declares it asimplementation(private), so the app module needs its own copy for the generated Kotlin to compile.expo prebuildmultiple times won't duplicate the manifest service entry or the gradle dependency.FirebaseMessagingServiceregistered (from manual setup or another SDK), the plugin skips registration and warns. The generated.ktfile is still written sincewithDangerousMod(file generation) runs beforewithAndroidManifest(conflict detection) in Expo's mod pipeline, and cross-mod dependencies would add unnecessary complexity. The orphaned file is harmless — it's an unregistered source file in the ephemeralandroid/directory thatexpo prebuildregenerates from scratch.Generated with Claude Code