0
# Android Features
1
2
Android-specific messaging capabilities including upstream messaging, message lifecycle events, and Google Play Services integration.
3
4
## Capabilities
5
6
### Upstream Messaging
7
8
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.
9
10
```typescript { .api }
11
/**
12
* Send upstream message to FCM server (Android only)
13
* @param message - RemoteMessage to send upstream
14
* @returns Promise that resolves when message is queued for sending
15
*/
16
function sendMessage(message: RemoteMessage): Promise<void>;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import messaging from '@react-native-firebase/messaging';
23
import { Platform } from 'react-native';
24
25
if (Platform.OS === 'android') {
26
// Send upstream message
27
await messaging().sendMessage({
28
messageId: 'unique-message-id',
29
to: 'your-sender-id@gcm.googleapis.com',
30
data: {
31
userId: 'current-user-id',
32
action: 'user_login',
33
timestamp: Date.now().toString(),
34
},
35
ttl: 3600, // Time to live in seconds
36
});
37
38
console.log('Upstream message sent');
39
}
40
41
// Modular API
42
import { getMessaging, sendMessage } from '@react-native-firebase/messaging';
43
44
if (Platform.OS === 'android') {
45
const messagingInstance = getMessaging();
46
await sendMessage(messagingInstance, {
47
messageId: 'analytics-event',
48
to: 'your-sender-id@gcm.googleapis.com',
49
data: {
50
event: 'user_interaction',
51
screen: 'home_screen',
52
},
53
});
54
}
55
```
56
57
### Message Lifecycle Events
58
59
Monitor the complete lifecycle of upstream messages including successful delivery and error conditions.
60
61
```typescript { .api }
62
/**
63
* Listen for successful message delivery to FCM (Android only)
64
* @param listener - Callback receiving message ID when sent successfully
65
* @returns Function to unsubscribe from message sent events
66
*/
67
function onMessageSent(listener: (messageId: string) => any): () => void;
68
69
/**
70
* Listen for upstream message send errors (Android only)
71
* @param listener - Callback receiving error details
72
* @returns Function to unsubscribe from send error events
73
*/
74
function onSendError(listener: (evt: SendErrorEvent) => any): () => void;
75
76
interface SendErrorEvent {
77
/** ID of the message that failed to send */
78
messageId: string;
79
/** Native Firebase error with failure details */
80
error: NativeFirebaseError;
81
}
82
```
83
84
**Usage Examples:**
85
86
```typescript
87
import messaging from '@react-native-firebase/messaging';
88
import { Platform } from 'react-native';
89
90
if (Platform.OS === 'android') {
91
// Listen for successful message delivery
92
const unsubscribeSent = messaging().onMessageSent(messageId => {
93
console.log('Message sent successfully:', messageId);
94
95
// Update local state or analytics
96
updateMessageStatus(messageId, 'sent');
97
});
98
99
// Listen for send errors
100
const unsubscribeError = messaging().onSendError(({ messageId, error }) => {
101
console.error('Message send failed:', messageId, error);
102
103
// Handle error (retry, log, notify user)
104
handleMessageSendError(messageId, error);
105
});
106
107
// Clean up listeners
108
// unsubscribeSent();
109
// unsubscribeError();
110
}
111
112
// Modular API
113
import { getMessaging, onMessageSent, onSendError } from '@react-native-firebase/messaging';
114
115
if (Platform.OS === 'android') {
116
const messagingInstance = getMessaging();
117
118
const unsubscribeSent = onMessageSent(messagingInstance, messageId => {
119
console.log('Sent:', messageId);
120
});
121
122
const unsubscribeError = onSendError(messagingInstance, ({ messageId, error }) => {
123
console.error('Send error:', messageId, error);
124
});
125
}
126
```
127
128
### Message Deletion Events
129
130
Handle server-side message deletion events that occur when FCM removes messages due to storage limits or connection issues.
131
132
```typescript { .api }
133
/**
134
* Listen for server message deletion events (Android only)
135
* @param listener - Callback called when FCM deletes pending messages
136
* @returns Function to unsubscribe from deletion events
137
*/
138
function onDeletedMessages(listener: () => void): () => void;
139
```
140
141
**Usage Examples:**
142
143
```typescript
144
import messaging from '@react-native-firebase/messaging';
145
import { Platform } from 'react-native';
146
147
if (Platform.OS === 'android') {
148
// Listen for message deletion events
149
const unsubscribe = messaging().onDeletedMessages(() => {
150
console.log('FCM deleted pending messages');
151
152
// Perform full sync with server
153
performFullDataSync();
154
155
// Notify user if needed
156
showMessageSyncNotification();
157
});
158
159
// Clean up listener
160
// unsubscribe();
161
}
162
163
// Modular API
164
import { getMessaging, onDeletedMessages } from '@react-native-firebase/messaging';
165
166
if (Platform.OS === 'android') {
167
const messagingInstance = getMessaging();
168
169
const unsubscribe = onDeletedMessages(messagingInstance, () => {
170
console.log('Messages were deleted by FCM');
171
// Handle deletion
172
});
173
}
174
```
175
176
### Google Play Services Integration
177
178
Manage notification delegation to Google Play Services for enhanced notification handling.
179
180
```typescript { .api }
181
/**
182
* Enable/disable notification delegation to Google Play Services (Android only)
183
* @param enabled - Whether to enable delegation
184
* @returns Promise that resolves when setting is updated
185
*/
186
function setNotificationDelegationEnabled(enabled: boolean): Promise<void>;
187
188
/**
189
* Check if notification delegation is enabled (Android only)
190
* @returns Boolean indicating delegation status
191
*/
192
readonly isNotificationDelegationEnabled: boolean;
193
```
194
195
**Usage Examples:**
196
197
```typescript
198
import messaging from '@react-native-firebase/messaging';
199
import { Platform } from 'react-native';
200
201
if (Platform.OS === 'android') {
202
// Check current delegation status
203
const delegationEnabled = messaging().isNotificationDelegationEnabled;
204
console.log('Delegation enabled:', delegationEnabled);
205
206
// Enable delegation (disables message handlers)
207
await messaging().setNotificationDelegationEnabled(true);
208
console.log('Notification delegation enabled');
209
210
// Disable for custom message handling
211
await messaging().setNotificationDelegationEnabled(false);
212
console.log('Custom message handling enabled');
213
}
214
215
// Modular API
216
import {
217
getMessaging,
218
isNotificationDelegationEnabled,
219
setNotificationDelegationEnabled
220
} from '@react-native-firebase/messaging';
221
222
if (Platform.OS === 'android') {
223
const messagingInstance = getMessaging();
224
const enabled = isNotificationDelegationEnabled(messagingInstance);
225
await setNotificationDelegationEnabled(messagingInstance, false);
226
}
227
```
228
229
## Android-Specific Message Properties
230
231
When handling messages on Android, additional properties are available:
232
233
```typescript { .api }
234
interface RemoteMessage {
235
/** Message priority (Android only) */
236
priority?: MessagePriority;
237
/** Original priority before processing (Android only) */
238
originalPriority?: MessagePriority;
239
}
240
241
enum MessagePriority {
242
/** Unknown priority (default) */
243
PRIORITY_UNKNOWN = 0,
244
/** High priority - can start foreground services */
245
PRIORITY_HIGH = 1,
246
/** Normal priority - restricted actions only */
247
PRIORITY_NORMAL = 2,
248
}
249
250
interface Notification {
251
android?: {
252
/** Sound file name (Android) */
253
sound?: string;
254
/** Notification channel ID (Android 8.0+) */
255
channelId?: string;
256
/** Notification color (Android) */
257
color?: string;
258
/** Small icon resource name (Android) */
259
smallIcon?: string;
260
/** Large image URL (Android) */
261
imageUrl?: string;
262
/** Deep link URL (Android) */
263
link?: string;
264
/** Notification count/badge (Android) */
265
count?: number;
266
/** Click action for notification (Android) */
267
clickAction?: string;
268
/** Notification priority (Android < 8.0) */
269
priority?: NotificationAndroidPriority;
270
/** Ticker text for accessibility (Android) */
271
ticker?: string;
272
/** Notification visibility on lock screen (Android) */
273
visibility?: NotificationAndroidVisibility;
274
};
275
}
276
```
277
278
## Android Integration Patterns
279
280
### Complete Android Upstream Messaging
281
282
```typescript
283
import messaging from '@react-native-firebase/messaging';
284
import { Platform } from 'react-native';
285
286
class AndroidMessagingManager {
287
private static messageQueue: Map<string, any> = new Map();
288
289
static async setupAndroidMessaging() {
290
if (Platform.OS !== 'android') return;
291
292
const messagingInstance = messaging();
293
294
// Set up message lifecycle listeners
295
messagingInstance.onMessageSent(messageId => {
296
console.log('Message sent:', messageId);
297
this.messageQueue.delete(messageId);
298
this.onMessageDelivered(messageId);
299
});
300
301
messagingInstance.onSendError(({ messageId, error }) => {
302
console.error('Send error:', messageId, error);
303
const messageData = this.messageQueue.get(messageId);
304
this.handleSendError(messageId, error, messageData);
305
});
306
307
// Handle message deletion
308
messagingInstance.onDeletedMessages(() => {
309
console.log('Messages deleted by FCM');
310
this.handleMessageDeletion();
311
});
312
}
313
314
static async sendUpstreamMessage(data: any, options: any = {}) {
315
if (Platform.OS !== 'android') return;
316
317
const messageId = `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
318
const message = {
319
messageId,
320
to: 'your-sender-id@gcm.googleapis.com',
321
data,
322
ttl: options.ttl || 3600,
323
...options,
324
};
325
326
// Store message for error handling
327
this.messageQueue.set(messageId, message);
328
329
try {
330
await messaging().sendMessage(message);
331
console.log('Message queued:', messageId);
332
return messageId;
333
} catch (error) {
334
this.messageQueue.delete(messageId);
335
throw error;
336
}
337
}
338
339
private static onMessageDelivered(messageId: string) {
340
// Handle successful delivery
341
console.log(`Message ${messageId} delivered successfully`);
342
}
343
344
private static handleSendError(messageId: string, error: any, messageData: any) {
345
// Implement retry logic or error reporting
346
console.error(`Message ${messageId} failed:`, error);
347
348
// Retry logic example
349
if (error.code === 'messaging/network-error') {
350
setTimeout(() => {
351
this.retryMessage(messageId, messageData);
352
}, 5000);
353
}
354
}
355
356
private static async retryMessage(messageId: string, messageData: any) {
357
try {
358
await messaging().sendMessage(messageData);
359
} catch (error) {
360
console.error('Retry failed:', error);
361
}
362
}
363
364
private static handleMessageDeletion() {
365
// Perform full sync with server
366
console.log('Performing full sync due to message deletion');
367
// Implement your sync logic here
368
}
369
}
370
371
// Initialize Android messaging
372
AndroidMessagingManager.setupAndroidMessaging();
373
```
374
375
### Android Background Processing
376
377
```typescript
378
import messaging from '@react-native-firebase/messaging';
379
import { Platform } from 'react-native';
380
381
// Android background message handler
382
messaging().setBackgroundMessageHandler(async remoteMessage => {
383
console.log('Background message on Android:', remoteMessage);
384
385
if (Platform.OS === 'android') {
386
// Android allows more background processing than iOS
387
try {
388
// Process the message
389
await processAndroidBackgroundMessage(remoteMessage);
390
391
// Send analytics
392
await sendAnalyticsEvent('background_message_processed', {
393
messageId: remoteMessage.messageId,
394
from: remoteMessage.from,
395
priority: remoteMessage.priority,
396
});
397
398
// Update local storage
399
await updateLocalMessageHistory(remoteMessage);
400
401
} catch (error) {
402
console.error('Android background processing error:', error);
403
}
404
}
405
});
406
407
async function processAndroidBackgroundMessage(remoteMessage: any) {
408
// Android-specific background processing
409
if (remoteMessage.priority === messaging.MessagePriority.PRIORITY_HIGH) {
410
// Handle high priority messages immediately
411
await handleHighPriorityMessage(remoteMessage);
412
} else {
413
// Queue normal priority messages
414
await queueMessageForProcessing(remoteMessage);
415
}
416
}
417
```
418
419
### Android Notification Delegation
420
421
```typescript
422
import messaging from '@react-native-firebase/messaging';
423
import { Platform } from 'react-native';
424
425
class AndroidNotificationManager {
426
static async configureNotificationHandling(useCustomHandling: boolean) {
427
if (Platform.OS !== 'android') return;
428
429
const messagingInstance = messaging();
430
431
if (useCustomHandling) {
432
// Disable delegation for custom handling
433
await messagingInstance.setNotificationDelegationEnabled(false);
434
console.log('Custom notification handling enabled');
435
436
// Set up custom message handlers
437
this.setupCustomMessageHandlers();
438
} else {
439
// Enable delegation to Google Play Services
440
await messagingInstance.setNotificationDelegationEnabled(true);
441
console.log('Google Play Services delegation enabled');
442
443
// Note: Message handlers won't work when delegation is enabled
444
}
445
}
446
447
private static setupCustomMessageHandlers() {
448
messaging().onMessage(async remoteMessage => {
449
// Custom foreground notification handling
450
await this.showCustomNotification(remoteMessage);
451
});
452
}
453
454
private static async showCustomNotification(remoteMessage: any) {
455
// Implement custom notification display logic
456
const notificationData = remoteMessage.notification;
457
const androidConfig = notificationData?.android;
458
459
// Use local notification library or custom implementation
460
console.log('Showing custom notification:', notificationData);
461
}
462
}
463
464
// Configure notification handling
465
AndroidNotificationManager.configureNotificationHandling(true); // Use custom handling
466
```
467
468
## Android Best Practices
469
470
1. **Upstream Messaging**: Use for analytics, status updates, and device-to-server communication
471
2. **Message Lifecycle**: Always monitor sent/error events for upstream messages
472
3. **Deletion Handling**: Implement full sync when messages are deleted by FCM
473
4. **Priority Handling**: Use message priority to determine processing urgency
474
5. **Background Processing**: Leverage Android's more permissive background processing
475
6. **Notification Channels**: Configure notification channels for Android 8.0+
476
7. **Delegation Decision**: Choose between custom handling and Google Play Services delegation
477
8. **Error Recovery**: Implement retry logic for failed upstream messages
478
479
## Android Debugging
480
481
Android-specific debugging approaches:
482
483
```typescript
484
import messaging from '@react-native-firebase/messaging';
485
import { Platform } from 'react-native';
486
487
if (__DEV__ && Platform.OS === 'android') {
488
console.log('Android Messaging Debug Info:');
489
console.log('Delegation Enabled:', messaging().isNotificationDelegationEnabled);
490
console.log('Auto Init Enabled:', messaging().isAutoInitEnabled);
491
492
// Monitor all Android-specific events
493
messaging().onMessageSent(messageId => {
494
console.log('DEBUG - Message sent:', messageId);
495
});
496
497
messaging().onSendError(({ messageId, error }) => {
498
console.log('DEBUG - Send error:', messageId, error);
499
});
500
501
messaging().onDeletedMessages(() => {
502
console.log('DEBUG - Messages deleted by FCM');
503
});
504
}
505
```
506
507
## Android Configuration
508
509
Key Android configuration considerations:
510
511
1. **Firebase Configuration**: Ensure `google-services.json` is properly configured
512
2. **Permissions**: Declare required permissions in `AndroidManifest.xml`
513
3. **Notification Channels**: Set up notification channels for Android 8.0+
514
4. **Background Services**: Configure background service limitations
515
5. **ProGuard Rules**: Add ProGuard rules if using code obfuscation
516
6. **Sender ID**: Configure sender ID in Firebase project settings