📱 Send Mobile Push Notifications with Flutter (Android)

This guide will walk you through sending push notifications to your Flutter application for Android using Pingram and Firebase Cloud Messaging (FCM).

Overview

Sending push notifications to Android devices is exclusively handled by Google’s Firebase Cloud Messaging (FCM). Implementing this from scratch requires significant backend infrastructure to manage device tokens and communicate with FCM.

Pingram simplifies this process by managing the entire backend complexity for you. Our Flutter SDK handles device token registration, and our service sends the notifications through FCM on your behalf.

The setup process is as follows:

  1. Set up a Firebase Project
  2. Connect Pingram to FCM
  3. Configure your Flutter project for Firebase
  4. Install and initialize the Pingram Flutter SDK
  5. Send a notification from your backend

1. Set up a Firebase Project

If you don’t have one already, you’ll need to create a Firebase project.

  1. Go to the Firebase Console and create a new project.
  2. Within your new project, navigate to Project Settings > General.
  3. Click the Android icon to add an Android app to your project. Use your Flutter app’s package name (e.g., com.example.my_app).
  4. Follow the on-screen instructions to register the app, and download the google-services.json file.
  5. Place the downloaded google-services.json file into the android/app/ directory of your Flutter project.

2. Connect Pingram to FCM

To allow Pingram to send notifications on your behalf, you need to provide it with your Firebase project’s credentials.

  1. In the Firebase Console, go to Project Settings > Service Accounts.
  2. Click Generate new private key. A JSON file containing your service account key will be downloaded.
DANGER

Important: Treat this file like a password. Never commit it to version control or expose it in your client-side application.

  1. Go to your Pingram Dashboard and navigate to the Settings page and then head to the PUSH tab.
  2. Copy the contents of the service account JSON file you downloaded from Firebase into the Android FCM form.

Your Pingram account is now connected to your Firebase project.


3. Configure your Flutter project for Firebase

Next, you need to add the Google Services plugin to your Flutter project’s Android configuration.

INFO

These instructions are based on the latest Flutter standards. If you have an older project, your file names or contents might differ slightly. Below we show both Groovy (.gradle) and Kotlin DSL (.kts) formats.

Using Groovy (build.gradle)

In android/build.gradle:

Add the google-services plugin to the buildscript dependencies.

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        // ...
        classpath 'com.google.gms:google-services:4.3.15'
    }
}

In android/app/build.gradle:

Apply the com.google.gms.google-services plugin at the top of the file.

apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
// ...

Using Kotlin DSL (build.gradle.kts)

If your project uses Kotlin DSL (.kts files), use the following instead.

In android/build.gradle.kts:

Add the plugin to the plugins block (create one at the top if it doesn’t exist):

plugins {
    id("com.google.gms.google-services") version "4.4.4" apply false
}

allprojects {
    // ... existing config
}

In android/app/build.gradle.kts:

Add the plugin to the existing plugins block:

plugins {
    id("com.android.application")
    id("kotlin-android")
    id("dev.flutter.flutter-gradle-plugin")
    id("com.google.gms.google-services")
}
// ...
WARNING

Build error: If you see “Dependency ':flutter_local_notifications' requires core library desugaring to be enabled”, add the following in android/app/build.gradle.kts:

  • In the compileOptions block: isCoreLibraryDesugaringEnabled = true
  • In a dependencies block: coreLibraryDesugaring(“com.android.tools:desugar_jdk_libs:2.1.4”)

Now, build your app to ensure the Firebase configuration is correct.

flutter build apk

4. Install and initialize the Pingram Flutter SDK

Our Flutter SDK makes it easy to register the device for push notifications.

Install the SDK from pub.dev:

flutter pub add notificationapi_flutter_sdk

Then, initialize the SDK in your main.dart file when your app starts. Your main widget must be a StatefulWidget so you can call NotificationAPI.setup() in initState. Use the static method NotificationAPI.setup() (not instance.configure()).

import 'package:flutter/material.dart';
import 'package:notificationapi_flutter_sdk/notificationapi_flutter_sdk.dart';

// ...

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    NotificationAPI.setup(
      clientId: 'YOUR_CLIENT_ID', // from Pingram dashboard
      userId: 'test_user_1234', // your app's user ID
      // region: 'eu' | 'ca' // Only if your account is in EU/Canada
    );
  }

  // ...
}

Optional: pass showForegroundNotifications: true to show native notification banners when the app is in the foreground.

This will automatically handle requesting push permissions and registering the device token with Pingram.

Parameters

ParameterTypeDescription
clientId*stringYour Pingram account clientId. You can get it from here.
userId*stringThe unique ID of the user in your system.
regionstringOptional. Set to eu or ca if your Pingram account is in EU or Canada.

5. Send a notification from your backend

With the SDK initialized, you can now trigger notifications from your backend. The userId must match the one used to initialize the SDK.

INFO

Ensure that the userId used to trigger the notification is the same as the userId used to initialize the frontend SDK.

Here’s an example using cURL:

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -d '{
    "type": "new_comment",
    "to": {
      "id": "test_user_123",
      "email": "test@example.com"
    },
    "mobile_push": {
      "title": "Hello",
      "message": "Hello, world!"
    }
  }' \
  "https://api.pingram.io/send"

Schematic Diagram

This diagram illustrates the entire flow, from app initialization to receiving a notification.

sequenceDiagram participant User participant FlutterApp participant "Pingram SDK" participant "Your Backend" participant Pingram participant "Firebase (FCM)" User->>FlutterApp: Opens App & Logs In FlutterApp->>"Pingram SDK": Initializes with Client ID & User ID "Pingram SDK"->>"Firebase (FCM)": Requests Push Token "Firebase (FCM)"-->>"Pingram SDK": Returns Push Token "Pingram SDK"->>Pingram: Sends User ID and Push Token "Your Backend"->>Pingram: Triggers Notification for User ID Pingram->>"Firebase (FCM)": Sends Notification Payload "Firebase (FCM)"->>FlutterApp: Delivers Push Notification FlutterApp->>User: Displays Notification
🔍 Click to enlarge diagram

Frequently Asked Questions (FAQs)

Why are my notifications not arriving?

There can be several reasons:

  • FCM Setup: Double-check that your google-services.json is correct and that your service account key is correctly uploaded to the Pingram dashboard.
  • User ID Mismatch: Ensure the userId in your Flutter app is identical to the one you’re sending to in the backend API call.
  • Device/Emulator Issues: Ensure your device or emulator has Google Play Services installed and is connected to the internet.
  • App State: On some Android versions, notification delivery behavior can change if the app is in the foreground, background, or terminated. Check Android’s documentation for details.

Why don’t I see notifications when the app is in the foreground?

On Android 8+, notifications are delivered through a channel. If that channel has default or low importance, the system will not show a heads-up banner when the app is in the foreground (you may still receive the payload in code). To show a visible banner while the app is open, create a high-importance notification channel (e.g. in MainActivity with NotificationManager.IMPORTANCE_HIGH) and set it as FCM’s default via the com.google.firebase.messaging.default_notification_channel_id meta-data in AndroidManifest.xml. Notifications when the app is in the background or terminated are unaffected.

How are expiring FCM tockens handled?

Pingram handles expiring FCM tokens automatically. Should tokens stop working for any reason, you’ll see the warnings in the logs in the dashboard. You do not need to handle any errors on your end, and this doesn’t count towards your usage.