Flutter SDK
flutter_notify_sphere on pub.dev. Push notifications for Android and iOS with delivery confirmation, click tracking, rich images, and custom sounds, built on Firebase Cloud Messaging.
Prerequisites#
- Dart 3.9 or newer (the package requires
sdk: ^3.9.0) - A Firebase project with Cloud Messaging enabled
- A notifySphere app with an App ID and API Token, and your Firebase service account uploaded. See Push setup.
- For iOS: your APNs authentication key (.p8) uploaded in Firebase → Project settings → Cloud Messaging
Install#
Add the SDK and the Firebase packages to pubspec.yaml, then run flutter pub get.
dependencies:
flutter:
sdk: flutter
flutter_notify_sphere: ^1.0.0
firebase_core: ^4.3.0
firebase_messaging: ^16.1.0Android setup#
Add google-services.json
Download
google-services.jsonfrom the Firebase console intoandroid/app/, and apply thecom.google.gms.google-servicesGradle plugin.Update AndroidManifest.xml
Add the permissions and the default icon and channel entries:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <uses-permission android:name="android.permission.VIBRATE"/> <!-- Only if you pass useLocationData: true to registerUser() --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <application ...> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@mipmap/ic_launcher" /> <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="notify_sphere_channel" /> </application> </manifest>Optional: custom sound
Put the audio file in
android/app/src/main/res/raw/(for examplecustom_sound.mp3) and entercustom_sound, without the extension, in the campaign's sound field.
Images in the payload (imageUrl) are downloaded and shown as expandable BigPictureStyle notifications automatically.
iOS setup#
Add GoogleService-Info.plist
Open
ios/Runner.xcworkspacein Xcode and addGoogleService-Info.plistto theRunnerfolder with "Copy items if needed" checked.Enable capabilities on Runner
Under Signing & Capabilities, add Push Notifications, Background Modes (Remote notifications, Background fetch), and App Groups with a group named
group.<your.bundle.id>.Add a Notification Service Extension
Choose File → New → Target → Notification Service Extension (Swift), for example named
ImageNotification. Give it the same App Group as Runner.Confirm delivery from the extension
Add
NotifySphereExtension.swiftto the extension and call it fromNotificationService.swift. Copy both files from the package README. The service also attaches images and applies custom sounds.// In NotificationService.swift, inside didReceive(_:withContentHandler:) NotifySphereExtension.didReceive(request) { NSLog("NotifySphere delivery confirmed") }
Usage#
1. Initialize in main.dart#
Initialize Firebase first, then the SDK. The background handler must be a top-level function annotated with @pragma('vm:entry-point').
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_notify_sphere/flutter_notify_sphere.dart';
// Must be a top-level function
@pragma('vm:entry-point')
Future<void> backgroundMessageHandler(RemoteMessage message) async {
debugPrint('Background message: ${message.data}');
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await FlutterNotifySphere().initialize(
showForegroundNotification: true,
onForegroundMessage: (RemoteMessage message) {
debugPrint('Foreground notification: ${message.data}');
},
onNotificationClick: (RemoteMessage? message) {
// Route to the screen this notification is about
},
backgroundMessageHandler: backgroundMessageHandler,
);
runApp(const MyApp());
}2. Register the user and device#
Call registerUser() after login, or on your home screen. Delivery and click events received before registration are queued and sent once it completes.
await FlutterNotifySphere().registerUser(
appId: 'YOUR_NOTIFYSPHERE_APP_ID',
apiKey: 'YOUR_NOTIFYSPHERE_API_TOKEN',
userData: {
'applicationUserId': 12345, // your internal user ID
'name': 'Jane Doe',
'email': 'jane@example.com',
},
useLocationData: false,
onFcmToken: (String? token) => debugPrint('FCM token: $token'),
onRegistrationComplete: (String? subscriptionId) {
debugPrint('Registered: $subscriptionId');
},
onError: (Object error) => debugPrint('Registration error: $error'),
);API reference#
initialize()#
| Field | Type | Description |
|---|---|---|
showForegroundNotification | bool | Show a heads-up notification while the app is open (default true) |
onForegroundMessage | (RemoteMessage) → void | Called when a push arrives in the foreground |
onNotificationClick | (RemoteMessage?) → void | Called when the user taps a notification |
backgroundMessageHandler | Future<void> Function(RemoteMessage) | Your top-level background handler |
registerUser()#
| Field | Type | Required | Description |
|---|---|---|---|
appId | String | Yes | Your notifySphere App ID |
apiKey | String | Yes | API Token from your dashboard |
userData | Map<String, dynamic> | Yes | User profile and custom metadata. Include applicationUserId. |
onFcmToken | (String?) → void | Yes | Receives the device FCM token |
onRegistrationComplete | (String?) → void | Yes | Receives the subscription ID |
onError | (Object) → void | No | Called if registration fails |
useLocationData | bool | No | Attach coordinates and a reverse-geocoded address (default false) |
Verify the integration#
- Run the app on a device and check the logs for the subscription ID from
onRegistrationComplete. - Send a test notification from the dashboard. The campaign's Delivered count should increase.
- Tap the notification. The Clicked count should increase.
- On iOS, test with the app closed to confirm the Notification Service Extension reports delivery.
Stuck or something unclear? Contact us and we'll help.