or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

android-features.mdindex.mdios-features.mdmessage-handling.mdpermissions-registration.mdtoken-management.mdtopic-management.md

android-features.mddocs/

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