Skillquality 0.46

cometchat-flutter-v6-push

Push notifications for CometChat Flutter UIKit v6 (beta, Bloc-based). Covers firebase_messaging setup for FCM (Android) + APNs (iOS via Firebase), CometChat dashboard PushPlatform configuration, token registration via the Notifications SDK, background isolate handler (Dart entry-

Price
free
Protocol
skill
Verified
no

What it does

Purpose

Push notifications for Flutter v6 (beta). Notifies users on incoming messages when the app is backgrounded or terminated. Two components: Firebase Messaging (FCM on Android, APNs forwarded via Firebase on iOS) on the client, plus CometChat dashboard PushPlatform configured to forward CometChat's webhook to Firebase.

This skill is for chat push (new messages). Calls/VoIP push has different mechanics — see cometchat-flutter-v6-calls/references/voip-push-end-to-end.md (or the relevant section of cometchat-flutter-v6-calls/SKILL.md rule 1.2).

Read these other skills first:

  • cometchat-flutter-v6-core — UIKitSettings, init/login order
  • cometchat-flutter-v5-push — sister skill (V5/GetX); same FCM stack with different client wiring
  • cometchat-flutter-v6-calls — calls VoIP push (overlap with this; both can coexist)

Ground truth:


1. Architecture

Flutter app
  ├── firebase_messaging — FCM token registration + receive
  └── Background isolate handler — handles pushes when app is killed

CometChat Notifications SDK (server-side, dashboard-managed)
  ├── PushPlatform configured (FCM key for Android, APNs cert for iOS)
  └── Listens for new-message events → fans out to FCM/APNs

CometChat dashboard
  └── Webhook → CometChat Notifications backend (no custom server needed for chat push)

Unlike Web Push (which requires you to run a push server), CometChat hosts the chat-push relay. Configure FCM/APNs creds in the dashboard's Notifications settings; CometChat does the rest.


2. Setup

Add packages

# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  cometchat_chat_uikit: ^6.0.0-beta2
  firebase_messaging: ^14.0.0
  firebase_core: ^2.0.0
  flutter_local_notifications: ^16.0.0    # for foreground notifications + iOS in-app banner

Firebase project setup

flutterfire configure

This wizard:

  • Asks which Firebase project to use (or creates one)
  • Asks which platforms (iOS, Android, Web)
  • Generates lib/firebase_options.dart
  • Places android/app/google-services.json
  • Places ios/Runner/GoogleService-Info.plist

If you don't have FlutterFire CLI: dart pub global activate flutterfire_cli.

Android — android/app/build.gradle

apply plugin: 'com.google.gms.google-services'

android {
  defaultConfig {
    minSdkVersion 26          // V6 floor; FCM needs 19+
  }
}

In android/build.gradle:

buildscript {
  dependencies {
    classpath 'com.google.gms:google-services:4.4.0'
  }
}

Android — manifest

<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />     <!-- Android 13+ -->

<application>
  <meta-data
    android:name="com.google.firebase.messaging.default_notification_channel_id"
    android:value="cometchat_messages" />
  <meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_notification" />
</application>

iOS — capabilities

In Xcode → target → Signing & Capabilities:

  • ☑ Push Notifications
  • ☑ Background Modes → Remote notifications

Then upload an APNs Authentication Key (.p8) to Firebase Console → Project Settings → Cloud Messaging → Apple app configuration. Token-based auth (.p8) is preferred over cert-based — same key works for sandbox + production.


3. Initialize Firebase + register for push

// lib/main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'firebase_options.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  // CRITICAL: register the background handler BEFORE runApp
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  runApp(const MyApp());
}

// Background handler MUST be a top-level function (not a closure inside a class)
// AND must be annotated with @pragma to survive tree-shaking in release builds
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // Runs in a SEPARATE isolate. No Bloc, no UI state — just data persistence
  // or local notifications if needed.
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  // CometChat Notifications backend already shows the system notification;
  // typically no extra work needed here.
}

The @pragma('vm:entry-point') annotation is non-negotiable. Without it, Flutter's tree-shaking removes the function in release builds and the background handler silently fails.


4. Token registration with CometChat

The CometChat Notifications backend needs the device's FCM token to send pushes. Register it via the CometChatNotifications SDK after login resolves:

// lib/services/push_service.dart
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/services.dart';

class PushService {
  final FirebaseMessaging _fcm = FirebaseMessaging.instance;

  /// Call AFTER CometChatUIKit.login resolves.
  Future<void> registerForPush() async {
    // Request permission (iOS prompts; Android 13+ prompts)
    final settings = await _fcm.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );
    if (settings.authorizationStatus != AuthorizationStatus.authorized) return;

    // Get the FCM token
    final token = await _fcm.getToken();
    if (token == null) return;

    // Register with CometChat — provider ID matches your dashboard PushPlatform
    await _registerWithCometChat(token, platform: defaultTargetPlatform);

    // Listen for token refresh — happens on OS upgrades, app reinstalls
    _fcm.onTokenRefresh.listen((newToken) async {
      await _registerWithCometChat(newToken, platform: defaultTargetPlatform);
    });
  }

  Future<void> unregister() async {
    final token = await _fcm.getToken();
    if (token == null) return;
    await _unregisterWithCometChat(token);
  }

  Future<void> _registerWithCometChat(String token, {required TargetPlatform platform}) async {
    // Audit 2026-05-14: the canonical SDK method is `PNRegistry.registerPNService`,
    // NOT `CometChatNotifications.registerPushToken` (which was cited in earlier
    // drafts of this doc but doesn't exist on the installed SDK).
    // Source: https://www.cometchat.com/docs/notifications/flutter-push-notifications-android.md
    //
    // The provider ID (FCM vs APN) is pulled from `AppCredentials.fcmProviderId`
    // (or the APN equivalent) at registration time — you don't pass it directly.
    PNRegistry.registerPNService(token, true, false);
  }

  Future<void> _unregisterWithCometChat(String token) async {
    // Same `PNRegistry` namespace — pass `false` as the second arg to unregister.
    PNRegistry.registerPNService(token, false, false);
  }
}

Audit 2026-05-14 — the symbols are PNRegistry.registerPNService(token, register, additionalFlag). Earlier drafts of this doc cited CometChatNotifications.registerPushToken / unregisterPushToken — those don't exist. Confirmed against the vendor docs at https://www.cometchat.com/docs/notifications/flutter-push-notifications-android.md. If you've copied the old symbols into your code, they will not compile.


5. Wire into the auth flow

// lib/main.dart (continued)
class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final PushService _push = PushService();

  @override
  void initState() {
    super.initState();
    _initCometChat();
  }

  Future<void> _initCometChat() async {
    final settings = (UIKitSettings.builder()
      ..appId = CometChatConfig.appId
      ..region = CometChatConfig.region
      ..authKey = CometChatConfig.authKey)
      .build();

    CometChatUIKit.init(
      uiKitSettings: settings,
      onSuccess: (_) async {
        // After login (in your AuthBloc or wherever)
        await _push.registerForPush();
        _setupForegroundHandler();
        _setupNotificationTapHandler();
      },
    );
  }

  void _setupForegroundHandler() {
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      // App is in foreground — system doesn't show a notification automatically.
      // Either show a flutter_local_notifications banner, or surface in-app via Bloc.
    });
  }

  void _setupNotificationTapHandler() {
    // Tap on notification while app is backgrounded
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      _navigateToConversation(message);
    });

    // Cold-start tap — app was terminated, user tapped notification
    FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
      if (message != null) _navigateToConversation(message);
    });
  }

  void _navigateToConversation(RemoteMessage message) {
    final data = message.data;
    final conversationId = data['conversationId'] as String?;
    final receiverType = data['receiverType'] as String?;
    if (conversationId == null) return;

    // Use a global navigator key (set on MaterialApp.navigatorKey) to navigate
    // from outside the widget tree
    AppNavigator.navigatorKey.currentState?.pushNamed(
      receiverType == 'group' ? '/messages/group/$conversationId' : '/messages/user/$conversationId',
    );
  }
}

6. CometChat dashboard PushPlatform

In the dashboard:

  1. Navigate to Notifications → Push Notifications.
  2. Add provider:
    • FCM for Android: paste the FCM Server Key (from Firebase Console → Project Settings → Cloud Messaging → Cloud Messaging API (Legacy)) OR the new HTTP v1 API service account JSON
    • APN for iOS: paste the .p8 + Team ID + Key ID, OR the .p12 (legacy)
  3. Save. CometChat now relays new-message events to FCM/APNs.

Use HTTP v1 API for FCM — Google deprecated the legacy server keys. The dashboard's UI lists both; pick HTTP v1 for new setups.


7. Foreground notifications

When the app is foregrounded, FCM does NOT show a system notification — onMessage fires instead and you decide what to do. Options:

A — In-app banner via Bloc

// In your AppBloc or a NotificationBloc
on<IncomingMessageNotification>((event, emit) {
  emit(state.copyWith(banner: BannerData(
    title: event.senderName,
    body: event.preview,
    onTap: () => navigatorKey.currentState?.pushNamed(...),
  )));
});

Render the banner in MaterialApp.builder.

B — Local notification via flutter_local_notifications

import 'package:flutter_local_notifications/flutter_local_notifications.dart';

final FlutterLocalNotificationsPlugin _localNotifs = FlutterLocalNotificationsPlugin();

Future<void> _showLocalNotif(RemoteMessage message) async {
  await _localNotifs.show(
    message.hashCode,
    message.notification?.title ?? '',
    message.notification?.body ?? '',
    NotificationDetails(
      android: AndroidNotificationDetails(
        'cometchat_messages',
        'Messages',
        importance: Importance.high,
        priority: Priority.high,
      ),
      iOS: DarwinNotificationDetails(),
    ),
    payload: jsonEncode(message.data),
  );
}

Initialize flutter_local_notifications once in main():

await _localNotifs.initialize(
  InitializationSettings(
    android: AndroidInitializationSettings('@mipmap/ic_launcher'),
    iOS: DarwinInitializationSettings(),
  ),
  onDidReceiveNotificationResponse: (response) {
    if (response.payload != null) {
      final data = jsonDecode(response.payload!);
      // navigate
    }
  },
);

8. Logout cleanup

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final PushService _push;

  on<LogoutRequested>((event, emit) async {
    await _push.unregister();             // CRITICAL — before SDK logout
    await CometChatUIKit.logout(/* ... */);
    emit(Unauthenticated());
  });
}

If you skip unregister, the previous user keeps getting notifications for the new user's messages.


9. v5 → v6 push migration

If migrating from v5:

ConcernV5V6
Listener patternGetX Get.put for push handlersBloc — handlers in app shell or a NotificationBloc
Init lifecycleCometChatUIKit.init callbackSame shape — onSuccess / onError
Token registration APIVerify against installed cometchat_chat_uikitSame — likely renamed; verify
Background handler@pragma('vm:entry-point') requiredUnchanged — Flutter framework requirement
Calls VoIP push interactioncometchat_calls_uikit ^5 separate packageCalls bundled into cometchat_chat_uikit ^6.0.0-beta2; VoIP push handled in cometchat-flutter-v6-calls references

The migration is small for push specifically — the FCM/firebase_messaging stack is unchanged; the deltas are in the surrounding architecture.


10. Anti-patterns

  1. Background handler missing @pragma('vm:entry-point'). Tree-shaken in release builds; works in debug. The "works in dev, fails in production" canary.
  2. Background handler as a closure inside a class. Must be a TOP-LEVEL function. Closures can't be passed across isolate boundaries.
  3. Calling _push.registerForPush() before login. CometChat doesn't know whose UID this token belongs to. Register from the post-login success callback.
  4. Skipping onTokenRefresh. OS upgrades and app reinstalls rotate the FCM token without warning. Listen to refresh and re-register.
  5. Using FCM legacy server keys. Google deprecated them. Use HTTP v1 API service account in CometChat dashboard.
  6. Not unregistering on logout. Previous user's notifications keep arriving for the new session.
  7. Showing a foreground notification AND an in-app banner for the same message. Pick one. The skill defaults to in-app banner (Bloc-driven) if the chat tab is active; system notification otherwise.
  8. flutter_local_notifications initialization missing icon resource. Crashes on Android with "Notification icon not found." Drop a ic_notification.png in android/app/src/main/res/drawable/.

11. Verification checklist

  • firebase_messaging ^14.0.0 + firebase_core ^2.0.0 in pubspec.yaml
  • flutterfire configure ran successfully; lib/firebase_options.dart exists
  • google-services.json in android/app/
  • GoogleService-Info.plist in ios/Runner/
  • iOS: Push Notifications + Remote-notification background mode capabilities enabled
  • iOS: APNs .p8 key uploaded to Firebase Console
  • Android: minSdkVersion 26 in android/app/build.gradle (V6 floor)
  • Android manifest: POST_NOTIFICATIONS permission + notification channel meta-data
  • Background handler is top-level + @pragma('vm:entry-point')
  • Background handler initialized via FirebaseMessaging.onBackgroundMessage BEFORE runApp
  • FCM/APN token registered with CometChat via PNRegistry.registerPNService(token, true, false) AFTER login (NOT CometChatNotifications.registerPushToken — that symbol doesn't exist; audit 2026-05-14)
  • onTokenRefresh re-registers
  • Foreground handler decides banner vs no-banner based on chat tab focus
  • onMessageOpenedApp + getInitialMessage both navigate to the conversation
  • Logout calls _push.unregister() BEFORE CometChatUIKit.logout()
  • Dashboard PushPlatform configured with FCM HTTP v1 + APNs .p8
  • Real-device smoke (NOT simulator): backgrounded app → message → notification rings + tapping opens chat thread

12. Pointers

  • cometchat-flutter-v5-push — V5/GetX sister skill (FCM stack unchanged; client wiring different)
  • cometchat-flutter-v6-calls/references/voip-push-end-to-end.md — calls VoIP push (overlap; both can coexist)
  • cometchat-flutter-v6-core — UIKitSettings, init/login order
  • cometchat-flutter-v6-troubleshooting — push debugging (token never registers, background handler doesn't fire, FCM payload not received)
  • cometchat-flutter-v6-migration — full V5→V6 migration recipe; push delta is one section

Capabilities

skillsource-cometchatskill-cometchat-flutter-v6-pushtopic-agent-skillstopic-ai-agenttopic-chattopic-claude-codetopic-cometchattopic-cursortopic-messagingtopic-nextjstopic-reacttopic-react-nativetopic-ui-kit

Install

Quality

0.46/ 1.00

deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 27 github stars · SKILL.md body (16,593 chars)

Provenance

Indexed fromgithub
Enriched2026-05-18 19:04:52Z · deterministic:skill-github:v1 · v1
First seen2026-05-18
Last seen2026-05-18

Agent access