Skip to main content

Introduction

Lerix delivers push notifications using each platform’s native service — Firebase Cloud Messaging (FCM) on Android, Apple Push Notification service (APNs) directly on iOS (no Firebase required), and standard Web Push (VAPID) on Flutter Web (no Firebase or OneSignal required there either). One package, one Lerix.notifications.* API, for all three. After you complete the Flutter installation, follow the platform steps below to enable push delivery in your app.
Make sure you have initialized the SDK with Lerix.init() before configuring push notifications.

Android configuration

No additional SDK setup is required for Android. You only need to add your Firebase google-services.json file to the project.
  1. Create or open your app in the Firebase Console.
  2. Download google-services.json for your Android app.
  3. Upload the file to the Lerix dashboard.
For the full setup steps, see Firebase’s Android client setup guide.

iOS configuration

You need an active Apple Developer account to send push notifications on iOS.

Set up APNs authentication

  1. In the Apple Developer portal, go to Certificates, Identifiers & Profiles → Keys.
  2. Create a new key with Apple Push Notifications service (APNs) enabled.
  3. Download the .p8 authentication key and note the Key ID. You can only download the key once.
  4. Upload the .p8 file to the Lerix dashboard.
For the full setup steps, see Apple’s guide to registering your app with APNs.

AppDelegate configuration

Add the following overrides to ios/Runner/AppDelegate.swift:
AppDelegate.swift

macOS configuration

macOS uses APNs with the same key you uploaded for iOS; no extra dashboard setup is needed. In Xcode, open macos/Runner:
  1. Signing & Capabilities: sign with your Apple team and add Push Notifications. An app signed “to run locally” can’t receive pushes.
  2. App Sandbox: allow Outgoing Connections (Client) so the SDK can reach Lerix.
  3. AppDelegate: forward the APNs callbacks in macos/Runner/AppDelegate.swift:
For Windows, see Windows push notifications (preview). Linux push isn’t supported yet.

Web configuration

Flutter Web is supported by the same lerix_flutter package — no separate JS SDK, no Firebase project. Two steps instead of Xcode’s:
  1. Copy the service worker. A Flutter package can’t add a file to your app’s web/ folder for you — copy the lerix_flutter package’s web_sw/lerix-sw.js into your app’s web/lerix-sw.js, so it’s served at your site’s root (e.g. https://yoursite.com/lerix-sw.js).
  2. Generate a Web Push key from the dashboard: Notifications → Settings → Web Push → Generate keys. One click — Lerix generates and stores the VAPID key pair for you; there’s nothing to copy into your code.
Lerix registers its worker on its own scope (/lerix/), so it runs alongside Flutter’s flutter_service_worker.js and a default flutter build web works as is. With lerix_flutter 0.0.1, the two workers competed for the root scope and Flutter’s replaced Lerix’s, so pushes were reported as sent but never shown. If you are still on 0.0.1, upgrade, or build with flutter build web --pwa-strategy=none.
On web, requestPermissions() does more than it does on mobile — see Platform differences below.

Huawei configuration

Coming Soon Huawei push notification support is not available yet. Check back soon for setup instructions.

Dashboard settings

Once you’ve uploaded your google-services.json (Android) and/or .p8 key (iOS), or generated a Web Push key pair, from the project’s Notifications → Settings tab in the dashboard, that platform card shows a Configured badge and the credentials it holds — click it again any time to review them or replace them.

Flutter code

All notification methods live on Lerix.notifications, and require await Lerix.notifications.init() to have run first — registration with APNs/FCM happens automatically as part of init(), so there’s no separate “register” call for the normal flow.
main.dart
Register setOnNotificationTapped somewhere that has access to navigation (e.g. a global navigatorKey), since a tap almost always means routing to a specific screen based on payload.metadata rather than just logging it.

The notification payload

setOnNotificationReceived and setOnNotificationTapped both receive an LerixNotificationPayload — the same shape on iOS and Android, regardless of how differently each platform actually delivers the underlying push:
A tap is delivered reliably even when it’s what launched the app from a fully terminated state — call setOnNotificationTapped right after Lerix.notifications.init() and any tap that happened before your app finished starting up is replayed automatically once the callback is registered.

Device identifiers: getDeviceId() vs getDeviceToken()

These look similar but answer different questions — use the right one for what you’re doing:
Both return null until registration completes, which Lerix.notifications.init() handles automatically — no separate call needed.

Sending a custom sound

Set sound when sending a notification — from the dashboard’s Send notification tab, or the REST API’s sound parameter — to play a bundled sound file instead of the device default:
  • The file must already ship inside your app project — Lerix only passes the filename through, it never hosts or uploads sound files.
  • iOS: pass the filename with its extension, e.g. sound.mp3 (.wav/.caf also supported).
  • Android: pass the filename without an extension, matching a file under res/raw/ (e.g. sound for res/raw/sound.mp3). Supported formats: .wav, .mp3, .ogg.
  • Web: not supported — the Web Notifications API has no cross-browser way to set a custom sound, so this parameter is ignored for web recipients.
On Android, a sound is locked in the first time it’s used on a given device — the OS fixes a notification channel’s sound at creation and never lets it change afterward. Sending a different sound value later creates a new channel rather than updating the old one; that’s expected Android behavior, not a bug.
No SDK code is required to play the sound — it happens automatically as part of the system notification.

Sending metadata

Attach arbitrary custom data with metadata (a JSON object) when sending — from the dashboard’s Send notification tab, or the REST API’s metadata parameter. It’s delivered back to the device inside payload.metadata:

Sending an image

Set imageUrl when sending a notification — from the dashboard’s Send notification tab, or the REST API’s imageUrl parameter — to show a rich image in the notification. Unlike sound, this is a normal https:// URL, not a bundled file — Lerix downloads it on your behalf.
  • Android: works automatically, no extra setup. The image renders as a BigPictureStyle notification.
  • Web: works automatically, no extra setup — the service worker renders it as the notification’s icon/image directly.
  • iOS: requires your app to have a Notification Service Extension — APNs has no native “image” field, so the OS needs a small extension to download and attach the image before displaying the notification. This is a one-time setup step per app:
    1. In Xcode: File → New → Target… → Notification Service Extension. Name it (e.g. NotificationServiceExtension).
    2. Replace the generated NotificationService.swift with the one from the lerix_flutter package at ios/NotificationServiceExtension/NotificationService.swift.
    3. Build and run — no other configuration needed. The backend automatically sets APNs’ mutable-content flag whenever a notification carries an imageUrl, which is what triggers your extension to run.
If iOS’s extension isn’t set up, an imageUrl is silently ignored on iOS — the notification still shows normally with no image, it doesn’t fail to send. Android is unaffected either way.
The image is also available in Dart as payload.imageUrl (in setOnNotificationReceived/setOnNotificationTapped) if you want to show it in a custom in-app banner, in addition to the OS rendering it natively.

Platform differences on web

Flutter Web uses the same Lerix.notifications.* calls as mobile, with a few real differences worth knowing about rather than being surprised by:
  • requestPermissions() does more on web. On mobile, push registration happens automatically inside init(), and requestPermissions() only concerns the visible-notification permission. A browser can’t subscribe to push before permission is granted, so on web, requestPermissions() also registers the service worker’s push subscription with the backend once the user allows it — the same method call, just doing double duty.
  • getSenderId() returns null on web — it’s an Android/FCM-only concept (Web Push uses VAPID, not Firebase).
  • getDeviceToken() also returns null on web — the browser’s PushSubscription isn’t a single opaque token the way APNs/FCM’s are, so there’s nothing meaningful to return. Use getDeviceId() on every platform instead.
  • Custom sound isn’t supported — see Sending a custom sound above.
  • Browser support: Chrome, Firefox, and Edge fully; Safari requires macOS 13+ or iOS 16.4+ — older Safari doesn’t support standard Web Push at all.

Target a user on every device

If your product also ships on other platforms (web, mobile or desktop), add them to the same project and link each install to your own user ID after login. Your backend can then send to externalUserIds and reach that person on every device in one request.
See Identify users for identity verification and a sending example.

Topics

Instead of targeting specific device tokens, a device can subscribe to a named topic — send one notification to the topic and every subscriber receives it. A topic doesn’t need to be created ahead of time; it’s created automatically the first time any device subscribes to it. You can also view, create, and delete topics from the Notifications → Topics tab in the dashboard.
To send to a topic, use the dashboard’s Send notification tab (select “Topic” as the audience), or call the REST API with sendByTopic: true.