Skip to main content

Flutter Quickstart

This guide walks you through integrating PushEngage push notifications into a Flutter application targeting both Android and iOS. Estimated time: 15 minutes.

After completing this guide, your app will receive push notifications on both platforms. See the Flutter SDK Reference for the full API.

Migration Guide: 0.0.x → 1.0.0

1.0.0 bumps the underlying iOS native SDK to 1.0.0, which splits the SDK into two CocoaPods so notification extension targets no longer link app-only code. Existing iOS integrations need three changes:

  1. Remove the Podfile build-setting override — delete the APPLICATION_EXTENSION_API_ONLY = 'No' line from your post_install block. It is no longer required.

  2. Switch extension target pods — in ios/Podfile, replace pod 'PushEngage', '0.0.6' (or earlier) inside each extension target block with pod 'PushEngageExtension'. The main Runner target continues to use pod 'PushEngage' (pulled transitively by pushengage_flutter_sdk).

  3. Update extension Swift code — in NotificationService.swift (and NotificationViewController.swift if present), replace import PushEngage with import PushEngageExtension, and the PushEngage class prefix on extension API calls with PushEngageExtension. Method names are unchanged.

    // Before
    import PushEngage
    PushEngage.didReceiveNotificationExtensionRequest(request, bestContentHandler: bestContent)
    PushEngage.serviceExtensionTimeWillExpire(request, content: bestAttemptContent)
    PushEngage.getCustomUIPayLoad(for: notification.request)

    // After
    import PushEngageExtension
    PushEngageExtension.didReceiveNotificationExtensionRequest(request, bestContentHandler: bestContent)
    PushEngageExtension.serviceExtensionTimeWillExpire(request, content: bestAttemptContent)
    PushEngageExtension.getCustomUIPayLoad(for: notification.request)

Dart API breaking change: deepLinkStream events now always carry data as a Map on both platforms. On Android the SDK previously delivered data as a JSON-encoded string — if your handler was decoding it manually, remove that step.

Prerequisites

  • Flutter SDK 3.x or higher
  • Android Studio (for Android builds) and/or Xcode (for iOS builds)
  • Firebase account (create one free) — required for Android
  • Apple Developer account with a valid App ID — required for iOS
  • APNs certificate or key (create one) — required for iOS
  • PushEngage account and App ID (see Get Your App ID)

Step 1 — Install the SDK

Add the dependency to pubspec.yaml:

pubspec.yaml
dependencies:
pushengage_flutter_sdk: ^1.0.0

Then run:

flutter pub get

Step 2 — Android Setup

Firebase Cloud Messaging (FCM)

  1. Open the Firebase console and sign in.
  2. Click Add Project (or select an existing one).
  3. Click the Android icon to add an Android app.
  4. Enter your app's package name (found in android/app/build.gradle under applicationId).
  5. Download google-services.json and place it at android/app/google-services.json.
  6. Generate the Service Account JSON: Firebase console → SettingsService accountsGenerate new private key.
  7. Retrieve the Sender ID: Firebase console → SettingsCloud Messaging tab.

Apply the Google Services Gradle Plugin

google-services.json only takes effect when the Google Services Gradle plugin is applied. Add it in two places:

  1. In your project-level android/build.gradle, add the classpath under buildscriptdependencies:

    android/build.gradle
    buildscript {
    dependencies {
    classpath 'com.google.gms:google-services:4.4.0'
    }
    }
  2. In your app-level android/app/build.gradle, apply the plugin:

    android/app/build.gradle
    plugins {
    id "com.android.application"
    id "kotlin-android"
    id "com.google.gms.google-services"
    // The Flutter Gradle Plugin must be applied after the Android and Kotlin plugins.
    id "dev.flutter.flutter-gradle-plugin"
    }

Without this plugin, FCM registration fails and no Android push token is generated.

Set the Activity Base Class

PushEngage's runtime permission and subscribe calls require the host activity to be a ComponentActivity. Flutter's default FlutterActivity is not one, so requestNotificationPermission() and subscribe() fail with an INVALID_ACTIVITY error. For requestNotificationPermission() the Dart layer reports this as a silent false (no exception is thrown); subscribe() returns a failure result with the error attached. Make MainActivity extend FlutterFragmentActivity:

android/app/src/main/kotlin/.../MainActivity.kt
import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity()

Connect to PushEngage Dashboard

  1. Log in to your PushEngage Dashboard.
  2. Navigate to Site Settings → Installation → Android SDK tab.
  3. Enter your Firebase Sender ID and upload the Service Account JSON.
  4. Click Update and copy the App ID.

Step 3 — iOS Setup

Open your iOS workspace in Xcode:

your_project_name/ios/Runner.xcworkspace

Enable Xcode Capabilities

  1. Select the root project and choose the Runner target.
  2. Go to Signing & Capabilities+ CapabilityPush Notifications.
  3. Click + CapabilityBackground Modes, then check Remote notifications and Background fetch.

Connect iOS to PushEngage Dashboard

  1. PushEngage Dashboard → Site Settings → Installation → iOS SDK tab.
  2. Upload your APNs certificate or key.
  3. Copy the App ID.

Step 4 — Add Notification Service Extension (iOS)

Create the Extension

  1. In Xcode, go to File → New → TargetNotification Service ExtensionNext.
  2. Name it PushEngageNotificationServiceExtensionFinish. Click Cancel when prompted to activate.
  3. Set the new target's Deployment Target to iOS 12 or above.

Configure Podfile

Open ios/Podfile and add the extension target at the bottom of the file:

ios/Podfile (additions)
target 'PushEngageNotificationServiceExtension' do
use_frameworks!
pod 'PushEngageExtension'
end
Extension-only module

Notification extensions link the companion PushEngageExtension pod, not the main PushEngage pod. PushEngageExtension is the extension-safe core that ships the three notification-extension APIs (didReceiveNotificationExtensionRequest, serviceExtensionTimeWillExpire, getCustomUIPayLoad). Linking the wrong pod can break push delivery on production builds.

Run in your ios/ directory:

pod repo update
pod install

Implement the Extension

Replace the auto-generated NotificationService.swift:

PushEngageNotificationServiceExtension/NotificationService.swift
import UserNotifications
import PushEngageExtension

@available(iOSApplicationExtension 12.0, *)
class NotificationService: UNNotificationServiceExtension {

var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
var request: UNNotificationRequest?

override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
self.request = request
self.contentHandler = contentHandler
self.bestAttemptContent = request.content.mutableCopy() as? UNMutableNotificationContent

if let bestContent = bestAttemptContent {
PushEngageExtension.didReceiveNotificationExtensionRequest(request, bestContentHandler: bestContent)
contentHandler(bestContent)
}
}

override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler,
let request = request,
let bestAttemptContent = bestAttemptContent {
guard let content = PushEngageExtension.serviceExtensionTimeWillExpire(
request, content: bestAttemptContent
) else {
contentHandler(bestAttemptContent)
return
}
contentHandler(content)
}
}
}

Step 5 — Add Notification Content Extension (iOS, Optional)

  1. In Xcode, go to File → New → TargetNotification Content ExtensionNext.
  2. Name it PushEngageNotificationContentExtensionFinish. Click Cancel when prompted.
  3. Set Deployment Target to iOS 12 or above.
  4. Add to ios/Podfile:
target 'PushEngageNotificationContentExtension' do
use_frameworks!
pod 'PushEngageExtension'
end

Run pod install in the ios/ directory.

Step 6 — Add App Groups (iOS)

  1. Select the Runner target in Xcode → Signing & Capabilities+ CapabilityApp Groups.
  2. Add a new App Group: group.com.yourcompany.yourapp.
  3. In ios/Runner/Info.plist, add:
    • Key: PushEngage_App_Group_Key
    • Value: group.com.yourcompany.yourapp
  4. In PushEngageNotificationServiceExtension/Info.plist, add the same key and value.
  5. Select the extension target → enable the same App Group under Signing & Capabilities.

Step 7 — Initialize the SDK

In lib/main.dart:

lib/main.dart
import 'package:flutter/material.dart';
import 'package:pushengage_flutter_sdk/pushengage_flutter_sdk.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatefulWidget {
const MyApp({super.key});


State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

void initState() {
super.initState();
_initPushEngage();
}

Future<void> _initPushEngage() async {
await PushEngage.setAppId('YOUR_APP_ID');
// Trigger the system permission prompt; on grant, the SDK auto-subscribes.
await PushEngage.requestNotificationPermission();
}


Widget build(BuildContext context) {
return const MaterialApp(
title: 'My App',
home: HomeScreen(),
);
}
}

For iOS distribution, initialize PushEngage in ios/Runner/AppDelegate.swift:

ios/Runner/AppDelegate.swift
import Flutter
import UIKit
import PushEngage

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

override init() {
super.init()
PushEngage.swizzleInjection(isEnabled: true)
}

override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
}
GeneratedPluginRegistrant.register(with: self)
PushEngage.setBadgeCount(count: 0)
PushEngage.setNotificationWillShowInForegroundHandler { notification, completion in
if notification.contentAvailable == 1 {
completion(nil)
} else {
completion(notification)
}
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
note

Replace YOUR_APP_ID with the App ID from Steps 2 or 3.

Step 8 — Send a Test Notification

  1. Build and run on a physical device (Android or iOS).
  2. Accept the notification permission prompt.
  3. In the PushEngage Dashboard → Campaign → Push Broadcasts → Create New Push Broadcast → send a test.

Troubleshooting

Android: notifications not received
Verify google-services.json is at android/app/google-services.json and that the Sender ID in the PushEngage Dashboard matches Firebase.

iOS: build sandboxing error
In Xcode → Build Settings → set User Script Sandboxing to No.

Next Steps