diff --git a/docs/messaging/usage/index.md b/docs/messaging/usage/index.md index 215d0d8e74..a0a6af4966 100644 --- a/docs/messaging/usage/index.md +++ b/docs/messaging/usage/index.md @@ -32,6 +32,66 @@ you can follow the manual installation steps for [iOS](/messaging/usage/installa # Expo +## Notification Icons and Colors + +The @react-native-firebase/messaging package includes an Expo config plugin that automatically configures Firebase notification icons and colors when using Expo managed workflow. + +### Android Configuration + +For Android, add notification configuration to your `app.json` or `app.config.js`: + +```json +{ + "expo": { + "name": "Your App", + "slug": "your-app", + "notification": { + "icon": "./assets/notification-icon.png", + "color": "#FF0000" + } + } +} +``` + +The plugin will automatically: +- Configure `com.google.firebase.messaging.default_notification_icon` in your Android manifest +- Configure `com.google.firebase.messaging.default_notification_color` in your Android manifest +- Use Expo's standard notification icon handling (requires a pure white PNG icon) + +> **Note**: Android notifications require a pure white icon for proper display. The notification icon should be a white silhouette on a transparent background. For more information, see [Expo's notification documentation](https://docs.expo.dev/versions/latest/config/app/#notification). + +### iOS Configuration + +iOS uses the app icon for notifications by default and doesn't require separate notification icon configuration. However, you can customize notification appearance through iOS-specific settings in your `app.json`: + +```json +{ + "expo": { + "ios": { + "icon": "./assets/ios-icon.png" + } + } +} +``` + +### Manual Setup + +If you need to manually configure the plugin, add it to your `app.json` or `app.config.js`: + +```json +{ + "expo": { + "plugins": [ + "@react-native-firebase/messaging" + ] + } +} +``` + +### No Configuration Warning + +If no notification configuration is detected, the plugin will display a warning message encouraging you to add proper notification icon configuration for Android compatibility. + ## iOS - Notifications entitlement Since Expo SDK51, Notifications entitlement is no longer always added to iOS projects during prebuild. If your project uses push notifications, you may need to add the aps-environment entitlement to your app config: diff --git a/packages/messaging/EXPO_EXAMPLE.md b/packages/messaging/EXPO_EXAMPLE.md new file mode 100644 index 0000000000..f8ae456d1a --- /dev/null +++ b/packages/messaging/EXPO_EXAMPLE.md @@ -0,0 +1,96 @@ +# @react-native-firebase/messaging Expo Configuration Example + +This example demonstrates how to configure Firebase Cloud Messaging notification icons and colors in an Expo managed workflow project. + +## Configuration + +Add the following to your `app.json` or `app.config.js`: + +```json +{ + "expo": { + "name": "Firebase Messaging Example", + "slug": "firebase-messaging-example", + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/icon.png", + "userInterfaceStyle": "light", + "splash": { + "image": "./assets/splash.png", + "resizeMode": "contain", + "backgroundColor": "#ffffff" + }, + "notification": { + "icon": "./assets/notification-icon.png", + "color": "#FF6B35" + }, + "assetBundlePatterns": [ + "**/*" + ], + "ios": { + "supportsTablet": true + }, + "android": { + "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", + "backgroundColor": "#FFFFFF" + } + }, + "web": { + "favicon": "./assets/favicon.png" + }, + "plugins": [ + "@react-native-firebase/messaging" + ] + } +} +``` + +## Key Points + +1. **Notification Icon**: Must be a pure white PNG icon on a transparent background +2. **Notification Color**: Hex color code that will be used to tint notification elements +3. **Plugin**: The `@react-native-firebase/messaging` plugin is automatically applied when the package is installed +4. **Android Only**: iOS uses the app icon for notifications by default + +## Creating the Notification Icon + +Your notification icon should be: +- **Pure white** silhouette on a transparent background +- **Square** aspect ratio +- **High resolution** (recommended 192x192px or higher) +- **Simple design** that's recognizable at small sizes + +Example using ImageMagick to convert a regular icon: +```bash +convert your-icon.png -colorspace Gray -threshold 50% -negate notification-icon.png +``` + +## Verification + +When you run `expo prebuild`, you should see these messages: +``` +[@react-native-firebase/messaging] Android notification icon configured from app.json +[@react-native-firebase/messaging] Android notification color configured from app.json +``` + +If you don't have notification configuration, you'll see a warning with instructions on how to add it. + +## Testing + +Send a test notification to verify your configuration: +```javascript +import messaging from '@react-native-firebase/messaging'; + +// Request permission (iOS) +await messaging().requestPermission(); + +// Get FCM token +const token = await messaging().getToken(); +console.log('FCM Token:', token); + +// Listen for messages +messaging().onMessage(async remoteMessage => { + console.log('Received message:', remoteMessage); +}); +``` \ No newline at end of file diff --git a/packages/messaging/README.md b/packages/messaging/README.md index e7dc3e770f..1e53f047de 100644 --- a/packages/messaging/README.md +++ b/packages/messaging/README.md @@ -36,6 +36,26 @@ Requires `@react-native-firebase/app` to be installed. yarn add @react-native-firebase/messaging ``` +## Expo Configuration + +This package includes an Expo config plugin for automatic configuration in Expo managed workflow. To configure notification icons and colors, add the following to your `app.json`: + +```json +{ + "expo": { + "notification": { + "icon": "./assets/notification-icon.png", + "color": "#FF0000" + }, + "plugins": [ + "@react-native-firebase/messaging" + ] + } +} +``` + +> **Note**: Android requires a pure white notification icon. See the [full documentation](https://rnfirebase.io/messaging/usage#expo) for details. + ## Documentation - [Quick Start](https://rnfirebase.io/messaging/usage) diff --git a/packages/messaging/plugin/__tests__/enhanced.test.ts b/packages/messaging/plugin/__tests__/enhanced.test.ts new file mode 100644 index 0000000000..7d3ec472fd --- /dev/null +++ b/packages/messaging/plugin/__tests__/enhanced.test.ts @@ -0,0 +1,131 @@ +import { describe, expect, it } from '@jest/globals'; +import { setFireBaseMessagingAndroidManifest } from '../src/android/setupFirebaseNotifationIcon'; +import { ExpoConfig } from '@expo/config-types'; +import { ManifestApplication } from '@expo/config-plugins/build/android/Manifest'; + +// Test to understand current functionality and identify improvements needed +describe('Enhanced Firebase Messaging Plugin Tests', function () { + + // Test case 1: Standard Expo notification configuration + it('handles standard Expo notification configuration', async function () { + const config: ExpoConfig = { + name: 'Test App', + slug: 'test-app', + notification: { + icon: './assets/notification-icon.png', + color: '#FF0000' + } + }; + + const manifestApplication: ManifestApplication = { + $: { 'android:name': '' }, + 'meta-data': [] + }; + + setFireBaseMessagingAndroidManifest(config, manifestApplication); + + // Should set notification icon + expect(manifestApplication['meta-data']).toContainEqual({ + $: { + 'android:name': 'com.google.firebase.messaging.default_notification_icon', + 'android:resource': '@drawable/notification_icon', + }, + }); + + // Should set notification color + expect(manifestApplication['meta-data']).toContainEqual({ + $: { + 'android:name': 'com.google.firebase.messaging.default_notification_color', + 'android:resource': '@color/notification_icon_color', + 'tools:replace': 'android:resource', + }, + }); + }); + + // Test case 2: Custom icon path + it('handles different icon path formats', async function () { + const config: ExpoConfig = { + name: 'Test App', + slug: 'test-app', + notification: { + icon: './custom/path/icon.png' + } + }; + + const manifestApplication: ManifestApplication = { + $: { 'android:name': '' }, + 'meta-data': [] + }; + + setFireBaseMessagingAndroidManifest(config, manifestApplication); + + // Currently hardcodes to @drawable/notification_icon regardless of path + expect(manifestApplication['meta-data']).toContainEqual({ + $: { + 'android:name': 'com.google.firebase.messaging.default_notification_icon', + 'android:resource': '@drawable/notification_icon', + }, + }); + }); + + // Test case 3: Missing notification config + it('warns when notification config is missing', async function () { + const warnOrig = console.warn; + const logOrig = console.log; + let warnCalled = false; + let warnMessage = ''; + console.warn = (message: string) => { + warnCalled = true; + warnMessage = message; + }; + console.log = () => {}; // Suppress log messages + + const config: ExpoConfig = { + name: 'Test App', + slug: 'test-app' + // No notification config + }; + + const manifestApplication: ManifestApplication = { + $: { 'android:name': '' }, + 'meta-data': [] + }; + + setFireBaseMessagingAndroidManifest(config, manifestApplication); + + expect(warnCalled).toBeTruthy(); + expect(warnMessage).toContain('[@react-native-firebase/messaging]'); + expect(warnMessage).toContain('notification configuration'); + console.warn = warnOrig; + console.log = logOrig; + }); + + // Test case 4: Successful configuration with logging + it('logs successful configuration', async function () { + const logOrig = console.log; + let logMessages: string[] = []; + console.log = (message: string) => { + logMessages.push(message); + }; + + const config: ExpoConfig = { + name: 'Test App', + slug: 'test-app', + notification: { + icon: './assets/notification-icon.png', + color: '#FF0000' + } + }; + + const manifestApplication: ManifestApplication = { + $: { 'android:name': '' }, + 'meta-data': [] + }; + + setFireBaseMessagingAndroidManifest(config, manifestApplication); + + expect(logMessages.some(msg => msg.includes('notification icon configured'))).toBeTruthy(); + expect(logMessages.some(msg => msg.includes('notification color configured'))).toBeTruthy(); + console.log = logOrig; + }); +}); \ No newline at end of file diff --git a/packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts b/packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts index 7a226e7a53..264b15af36 100644 --- a/packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts +++ b/packages/messaging/plugin/src/android/setupFirebaseNotifationIcon.ts @@ -35,7 +35,16 @@ export function setFireBaseMessagingAndroidManifest( // This warning is important because the notification icon can only use pure white on Android. By default, the system uses the app icon as the notification icon, but the app icon is usually not pure white, so you need to set the notification icon // eslint-disable-next-line no-console console.warn( - 'For Android 8.0 and above, it is necessary to set the notification icon to ensure correct display. Otherwise, the notification will not show the correct icon. For more information, visit https://docs.expo.dev/versions/latest/config/app/#notification', + '[@react-native-firebase/messaging] For Android, it is necessary to set a notification icon to ensure correct display. Add notification configuration to your app.json:\n' + + '{\n' + + ' "expo": {\n' + + ' "notification": {\n' + + ' "icon": "./assets/notification-icon.png",\n' + + ' "color": "#FF0000"\n' + + ' }\n' + + ' }\n' + + '}\n' + + 'For more information, visit https://docs.expo.dev/versions/latest/config/app/#notification', ); return config; } @@ -56,6 +65,11 @@ export function setFireBaseMessagingAndroidManifest( 'android:resource': '@drawable/notification_icon', }, }); + + // eslint-disable-next-line no-console + console.log( + '[@react-native-firebase/messaging] Android notification icon configured from app.json', + ); } if ( @@ -71,6 +85,11 @@ export function setFireBaseMessagingAndroidManifest( 'tools:replace': 'android:resource', }, }); + + // eslint-disable-next-line no-console + console.log( + '[@react-native-firebase/messaging] Android notification color configured from app.json', + ); } return application;