CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-native-firebase--messaging

React Native Firebase integration for Firebase Cloud Messaging (FCM) providing cross-platform push notification capabilities

Pending
Overview
Eval results
Files

android-features.mddocs/

Android Features

Android-specific messaging capabilities including upstream messaging, message lifecycle events, and Google Play Services integration.

Capabilities

Upstream Messaging

Send messages from the device to your app server through FCM. This allows device-to-server communication for analytics, status updates, or other data synchronization.

/**
 * Send upstream message to FCM server (Android only)
 * @param message - RemoteMessage to send upstream
 * @returns Promise that resolves when message is queued for sending
 */
function sendMessage(message: RemoteMessage): Promise<void>;

Usage Examples:

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

if (Platform.OS === 'android') {
  // Send upstream message
  await messaging().sendMessage({
    messageId: 'unique-message-id',
    to: 'your-sender-id@gcm.googleapis.com',
    data: {
      userId: 'current-user-id',
      action: 'user_login',
      timestamp: Date.now().toString(),
    },
    ttl: 3600, // Time to live in seconds
  });
  
  console.log('Upstream message sent');
}

// Modular API
import { getMessaging, sendMessage } from '@react-native-firebase/messaging';

if (Platform.OS === 'android') {
  const messagingInstance = getMessaging();
  await sendMessage(messagingInstance, {
    messageId: 'analytics-event',
    to: 'your-sender-id@gcm.googleapis.com',
    data: {
      event: 'user_interaction',
      screen: 'home_screen',
    },
  });
}

Message Lifecycle Events

Monitor the complete lifecycle of upstream messages including successful delivery and error conditions.

/**
 * Listen for successful message delivery to FCM (Android only)
 * @param listener - Callback receiving message ID when sent successfully
 * @returns Function to unsubscribe from message sent events
 */
function onMessageSent(listener: (messageId: string) => any): () => void;

/**
 * Listen for upstream message send errors (Android only)
 * @param listener - Callback receiving error details
 * @returns Function to unsubscribe from send error events
 */
function onSendError(listener: (evt: SendErrorEvent) => any): () => void;

interface SendErrorEvent {
  /** ID of the message that failed to send */
  messageId: string;
  /** Native Firebase error with failure details */
  error: NativeFirebaseError;
}

Usage Examples:

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

if (Platform.OS === 'android') {
  // Listen for successful message delivery
  const unsubscribeSent = messaging().onMessageSent(messageId => {
    console.log('Message sent successfully:', messageId);
    
    // Update local state or analytics
    updateMessageStatus(messageId, 'sent');
  });
  
  // Listen for send errors
  const unsubscribeError = messaging().onSendError(({ messageId, error }) => {
    console.error('Message send failed:', messageId, error);
    
    // Handle error (retry, log, notify user)
    handleMessageSendError(messageId, error);
  });
  
  // Clean up listeners
  // unsubscribeSent();
  // unsubscribeError();
}

// Modular API
import { getMessaging, onMessageSent, onSendError } from '@react-native-firebase/messaging';

if (Platform.OS === 'android') {
  const messagingInstance = getMessaging();
  
  const unsubscribeSent = onMessageSent(messagingInstance, messageId => {
    console.log('Sent:', messageId);
  });
  
  const unsubscribeError = onSendError(messagingInstance, ({ messageId, error }) => {
    console.error('Send error:', messageId, error);
  });
}

Message Deletion Events

Handle server-side message deletion events that occur when FCM removes messages due to storage limits or connection issues.

/**
 * Listen for server message deletion events (Android only)
 * @param listener - Callback called when FCM deletes pending messages
 * @returns Function to unsubscribe from deletion events
 */
function onDeletedMessages(listener: () => void): () => void;

Usage Examples:

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

if (Platform.OS === 'android') {
  // Listen for message deletion events
  const unsubscribe = messaging().onDeletedMessages(() => {
    console.log('FCM deleted pending messages');
    
    // Perform full sync with server
    performFullDataSync();
    
    // Notify user if needed
    showMessageSyncNotification();
  });
  
  // Clean up listener
  // unsubscribe();
}

// Modular API
import { getMessaging, onDeletedMessages } from '@react-native-firebase/messaging';

if (Platform.OS === 'android') {
  const messagingInstance = getMessaging();
  
  const unsubscribe = onDeletedMessages(messagingInstance, () => {
    console.log('Messages were deleted by FCM');
    // Handle deletion
  });
}

Google Play Services Integration

Manage notification delegation to Google Play Services for enhanced notification handling.

/**
 * Enable/disable notification delegation to Google Play Services (Android only)
 * @param enabled - Whether to enable delegation
 * @returns Promise that resolves when setting is updated
 */
function setNotificationDelegationEnabled(enabled: boolean): Promise<void>;

/**
 * Check if notification delegation is enabled (Android only)
 * @returns Boolean indicating delegation status
 */
readonly isNotificationDelegationEnabled: boolean;

Usage Examples:

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

if (Platform.OS === 'android') {
  // Check current delegation status
  const delegationEnabled = messaging().isNotificationDelegationEnabled;
  console.log('Delegation enabled:', delegationEnabled);
  
  // Enable delegation (disables message handlers)
  await messaging().setNotificationDelegationEnabled(true);
  console.log('Notification delegation enabled');
  
  // Disable for custom message handling
  await messaging().setNotificationDelegationEnabled(false);
  console.log('Custom message handling enabled');
}

// Modular API
import { 
  getMessaging, 
  isNotificationDelegationEnabled,
  setNotificationDelegationEnabled 
} from '@react-native-firebase/messaging';

if (Platform.OS === 'android') {
  const messagingInstance = getMessaging();
  const enabled = isNotificationDelegationEnabled(messagingInstance);
  await setNotificationDelegationEnabled(messagingInstance, false);
}

Android-Specific Message Properties

When handling messages on Android, additional properties are available:

interface RemoteMessage {
  /** Message priority (Android only) */
  priority?: MessagePriority;
  /** Original priority before processing (Android only) */
  originalPriority?: MessagePriority;
}

enum MessagePriority {
  /** Unknown priority (default) */
  PRIORITY_UNKNOWN = 0,
  /** High priority - can start foreground services */
  PRIORITY_HIGH = 1,
  /** Normal priority - restricted actions only */
  PRIORITY_NORMAL = 2,
}

interface Notification {
  android?: {
    /** Sound file name (Android) */
    sound?: string;
    /** Notification channel ID (Android 8.0+) */
    channelId?: string;
    /** Notification color (Android) */
    color?: string;
    /** Small icon resource name (Android) */
    smallIcon?: string;
    /** Large image URL (Android) */
    imageUrl?: string;
    /** Deep link URL (Android) */
    link?: string;
    /** Notification count/badge (Android) */
    count?: number;
    /** Click action for notification (Android) */
    clickAction?: string;
    /** Notification priority (Android < 8.0) */
    priority?: NotificationAndroidPriority;
    /** Ticker text for accessibility (Android) */
    ticker?: string;
    /** Notification visibility on lock screen (Android) */
    visibility?: NotificationAndroidVisibility;
  };
}

Android Integration Patterns

Complete Android Upstream Messaging

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

class AndroidMessagingManager {
  private static messageQueue: Map<string, any> = new Map();
  
  static async setupAndroidMessaging() {
    if (Platform.OS !== 'android') return;
    
    const messagingInstance = messaging();
    
    // Set up message lifecycle listeners
    messagingInstance.onMessageSent(messageId => {
      console.log('Message sent:', messageId);
      this.messageQueue.delete(messageId);
      this.onMessageDelivered(messageId);
    });
    
    messagingInstance.onSendError(({ messageId, error }) => {
      console.error('Send error:', messageId, error);
      const messageData = this.messageQueue.get(messageId);
      this.handleSendError(messageId, error, messageData);
    });
    
    // Handle message deletion
    messagingInstance.onDeletedMessages(() => {
      console.log('Messages deleted by FCM');
      this.handleMessageDeletion();
    });
  }
  
  static async sendUpstreamMessage(data: any, options: any = {}) {
    if (Platform.OS !== 'android') return;
    
    const messageId = `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    const message = {
      messageId,
      to: 'your-sender-id@gcm.googleapis.com',
      data,
      ttl: options.ttl || 3600,
      ...options,
    };
    
    // Store message for error handling
    this.messageQueue.set(messageId, message);
    
    try {
      await messaging().sendMessage(message);
      console.log('Message queued:', messageId);
      return messageId;
    } catch (error) {
      this.messageQueue.delete(messageId);
      throw error;
    }
  }
  
  private static onMessageDelivered(messageId: string) {
    // Handle successful delivery
    console.log(`Message ${messageId} delivered successfully`);
  }
  
  private static handleSendError(messageId: string, error: any, messageData: any) {
    // Implement retry logic or error reporting
    console.error(`Message ${messageId} failed:`, error);
    
    // Retry logic example
    if (error.code === 'messaging/network-error') {
      setTimeout(() => {
        this.retryMessage(messageId, messageData);
      }, 5000);
    }
  }
  
  private static async retryMessage(messageId: string, messageData: any) {
    try {
      await messaging().sendMessage(messageData);
    } catch (error) {
      console.error('Retry failed:', error);
    }
  }
  
  private static handleMessageDeletion() {
    // Perform full sync with server
    console.log('Performing full sync due to message deletion');
    // Implement your sync logic here
  }
}

// Initialize Android messaging
AndroidMessagingManager.setupAndroidMessaging();

Android Background Processing

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

// Android background message handler
messaging().setBackgroundMessageHandler(async remoteMessage => {
  console.log('Background message on Android:', remoteMessage);
  
  if (Platform.OS === 'android') {
    // Android allows more background processing than iOS
    try {
      // Process the message
      await processAndroidBackgroundMessage(remoteMessage);
      
      // Send analytics
      await sendAnalyticsEvent('background_message_processed', {
        messageId: remoteMessage.messageId,
        from: remoteMessage.from,
        priority: remoteMessage.priority,
      });
      
      // Update local storage
      await updateLocalMessageHistory(remoteMessage);
      
    } catch (error) {
      console.error('Android background processing error:', error);
    }
  }
});

async function processAndroidBackgroundMessage(remoteMessage: any) {
  // Android-specific background processing
  if (remoteMessage.priority === messaging.MessagePriority.PRIORITY_HIGH) {
    // Handle high priority messages immediately
    await handleHighPriorityMessage(remoteMessage);
  } else {
    // Queue normal priority messages
    await queueMessageForProcessing(remoteMessage);
  }
}

Android Notification Delegation

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

class AndroidNotificationManager {
  static async configureNotificationHandling(useCustomHandling: boolean) {
    if (Platform.OS !== 'android') return;
    
    const messagingInstance = messaging();
    
    if (useCustomHandling) {
      // Disable delegation for custom handling
      await messagingInstance.setNotificationDelegationEnabled(false);
      console.log('Custom notification handling enabled');
      
      // Set up custom message handlers
      this.setupCustomMessageHandlers();
    } else {
      // Enable delegation to Google Play Services
      await messagingInstance.setNotificationDelegationEnabled(true);
      console.log('Google Play Services delegation enabled');
      
      // Note: Message handlers won't work when delegation is enabled
    }
  }
  
  private static setupCustomMessageHandlers() {
    messaging().onMessage(async remoteMessage => {
      // Custom foreground notification handling
      await this.showCustomNotification(remoteMessage);
    });
  }
  
  private static async showCustomNotification(remoteMessage: any) {
    // Implement custom notification display logic
    const notificationData = remoteMessage.notification;
    const androidConfig = notificationData?.android;
    
    // Use local notification library or custom implementation
    console.log('Showing custom notification:', notificationData);
  }
}

// Configure notification handling
AndroidNotificationManager.configureNotificationHandling(true); // Use custom handling

Android Best Practices

  1. Upstream Messaging: Use for analytics, status updates, and device-to-server communication
  2. Message Lifecycle: Always monitor sent/error events for upstream messages
  3. Deletion Handling: Implement full sync when messages are deleted by FCM
  4. Priority Handling: Use message priority to determine processing urgency
  5. Background Processing: Leverage Android's more permissive background processing
  6. Notification Channels: Configure notification channels for Android 8.0+
  7. Delegation Decision: Choose between custom handling and Google Play Services delegation
  8. Error Recovery: Implement retry logic for failed upstream messages

Android Debugging

Android-specific debugging approaches:

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

if (__DEV__ && Platform.OS === 'android') {
  console.log('Android Messaging Debug Info:');
  console.log('Delegation Enabled:', messaging().isNotificationDelegationEnabled);
  console.log('Auto Init Enabled:', messaging().isAutoInitEnabled);
  
  // Monitor all Android-specific events
  messaging().onMessageSent(messageId => {
    console.log('DEBUG - Message sent:', messageId);
  });
  
  messaging().onSendError(({ messageId, error }) => {
    console.log('DEBUG - Send error:', messageId, error);
  });
  
  messaging().onDeletedMessages(() => {
    console.log('DEBUG - Messages deleted by FCM');
  });
}

Android Configuration

Key Android configuration considerations:

  1. Firebase Configuration: Ensure google-services.json is properly configured
  2. Permissions: Declare required permissions in AndroidManifest.xml
  3. Notification Channels: Set up notification channels for Android 8.0+
  4. Background Services: Configure background service limitations
  5. ProGuard Rules: Add ProGuard rules if using code obfuscation
  6. Sender ID: Configure sender ID in Firebase project settings

Install with Tessl CLI

npx tessl i tessl/npm-react-native-firebase--messaging

docs

android-features.md

index.md

ios-features.md

message-handling.md

permissions-registration.md

token-management.md

topic-management.md

tile.json