Library / SDK
OneSignal/OneSignal-Flutter-SDK avatar
OneSignal/OneSignal-Flutter-SDK

OneSignal Flutter SDK: multi-channel messaging with a dependency-resolution trap

OneSignal makes engaging customers simple and is the fastest, most reliable service to send push notifications, in-app messages, SMS, and emails. This plugin makes it easy to integrate your Fluter app with OneSignal. https://onesignal.com

653 stars238 forksDartNOASSERTION

At a glance

What is it?
The OneSignal Flutter SDK wraps push notifications, in-app messages, SMS and email behind one Dart API for iOS and Android apps. It is well maintained, but it carries a migration advisory about feature parity in the 5.x user-centric APIs, and its location-exclusion switch only takes effect when dependencies are resolved, which makes cached builds the sharpest edge in the documentation.
Who is it for?
OneSignal's Flutter SDK fits a Flutter team that wants push, in-app, SMS and email through a single dashboard and a single Dart surface, and that has a staged rollout available on both app stores to de-risk an upgrade.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Dart, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One Dart surface for four messaging channels

OneSignal is described as a free email, sms, push notification and in-app message service for mobile apps. The SDK in this repository is the Flutter client for that service, and the README states its purpose plainly: it makes it easy to integrate your Flutter iOS and/or Android apps with OneSignal.

So the library is a wrapper, and understanding what it wraps matters for the decision. On one side there is the OneSignal service with its dashboard, targeting and audience handling. On the other side there is your Flutter app, which calls into native iOS and Android code. The topics list covers android, ios, flutter, notifications, push-notifications, in-app-messaging, email and sms, which is the honest scope of a multi-channel client rather than a push-only plugin.

The codebase is Dart with native platform directories: lib/ for the Dart API, android/ and ios/ for the native sides, plus pubspec.yaml, analysis_options.yaml and a test/ directory with a test.json fixture. The repository also carries examples/ with several demo applications, including demo-no-location and demo-no-location-pods, which mirror the configuration scenarios described in the documentation.

Release cadence is fast. Recent tags include 5.6.12 on 2026-09-22, 5.7.0 on 2026-09-23 and 5.7.1 on 2026-10-16, and the last push was on 2026-10-17. The changelog is the release tags themselves, as the README points out.

One licensing note: the repository is filed under a custom licence that GitHub cannot classify, and the LICENSE file is the authoritative text, which is worth checking before you embed it in a closed-source app.

The migration advisory admits the new APIs are not at parity

The most important paragraph in the README is the advisory at the top, and it is the kind of statement vendors rarely volunteer.

The README says the new user-centric APIs and v5.x.x SDKs offer an improved user and data management experience, and then qualifies it: they may not be at 1:1 feature parity with the previous versions yet. For a team upgrading from an older OneSignal SDK, that sentence is the whole risk statement.

The recommended mitigation is staged release rather than a big-bang upgrade. The README suggests using the phased rollout capabilities of iOS and Android for existing apps, and links the iOS Phased Rollout documentation for App Store Connect and Google Play Staged Rollouts. That is a concrete operational answer: ship the new SDK to a slice of users, watch, then widen.

The fallback is human support. The README points to [email protected] for anyone who hits problems or has concerns during a migration, and separately notes that the GitHub issue tracker is for SDK feature requests and bugs while account issues go through the OneSignal dashboard.

Inside the repository there is a MIGRATION_GUIDE.md alongside CHANGELOG.md and CONTRIBUTING.md, so the detailed upgrade path exists. The README just makes the point that it is a path with edges, not a formality.

Excluding the location module happens at resolution time

The longest section of the README covers a single environment variable, and the reason it needs a whole section is a design decision worth understanding.

If your app does not use OneSignal.Location, you can exclude the native location module from iOS and Android builds. The switch is ONESIGNAL_DISABLE_LOCATION set in the environment before resolving or building, and it applies to Swift Package Manager, CocoaPods and Android Gradle builds alike. The value is case-insensitive and 1 is also accepted.

In GitHub Actions you would set it at the job or step level so all three build systems inherit it:

yaml
env:
  ONESIGNAL_DISABLE_LOCATION: true

The observable effect is stated as well: with the location module disabled, calls to OneSignal.Location are ignored on Android, and OneSignal.Location.isShared() returns false.

The wording before resolving or building is the important part. The variable is not read at runtime and not read at compile time; it changes which pods and packages get resolved, and the resolution result is cached. That is why the same flag behaves differently depending on whether you have a fresh checkout or an existing project with cached packages, and it is the reason the documentation spends more words on cache clearing than on the variable itself.

For a Flutter team, this is a plugin whose build configuration is partly decided by the environment of the machine that runs the build, which is a meaningful operational property.

CocoaPods requires one identical subspec set across targets

If you build with CocoaPods and use extension targets, this is the failure you will hit, and the README reproduces the exact error:

code
error: Multiple commands produce '.../XCFrameworkIntermediates/OneSignalXCFramework/OneSignalCore/OneSignalCore.framework'

The cause is in how CocoaPods handles the umbrella pod. The README explains that CocoaPods only builds OneSignalXCFramework once when every target in your Podfile resolves the same set of subspecs. If the sets differ, it creates one pod variant per set, and each variant tries to write the same extracted framework, which is what produces the conflicting output error.

The fix depends on whether you disabled location. With location disabled, the plugin resolves OneSignalXCFramework/OneSignal and OneSignalXCFramework/OneSignalInAppMessages, so every Notification Service Extension or Widget Extension target must declare those same two subspecs:

ruby
target 'OneSignalNotificationServiceExtension' do
  use_frameworks!
  pod 'OneSignalXCFramework/OneSignal', '>= 5.0.0', '< 6.0'
  pod 'OneSignalXCFramework/OneSignalInAppMessages', '>= 5.0.0', '< 6.0'
end

Without the environment variable set, the plugin resolves the umbrella pod, so extension targets should declare pod 'OneSignalXCFramework' instead. Either way the rule is the same: the app target and every extension target must request an identical subspec set.

That conditional is the trap. The correct Podfile depends on a build environment variable, so two developers or two CI jobs with different exported variables need different Podfiles for the same app.

Cached packages ignore the flag unless you clear them

The README warns about this directly, and the warning is the most useful operational advice in the document.

The environment variable is only read when dependencies are resolved, and each platform caches the resolved set. So if you change the variable on an existing project, you must clear the relevant cache and re-resolve in a shell where the variable is exported. Otherwise a stale build can keep, or drop, the location module regardless of the new value.

For Swift Package Manager the sequence clears the Flutter build, the iOS build directory, the SwiftPM cache and Xcode DerivedData before rebuilding with the variable exported:

sh
flutter clean
rm -rf ios/.build
rm -rf ~/Library/Caches/org.swift.swiftpm ~/Library/Developer/Xcode/DerivedData/*
ONESIGNAL_DISABLE_LOCATION=true flutter build ios

For CocoaPods it deintegrates the pods and removes the Pods directory and the lockfile, then reinstalls:

sh
cd ios
pod deintegrate
rm -rf Pods Podfile.lock
ONESIGNAL_DISABLE_LOCATION=true pod install

Android Gradle re-reads the variable on each configuration, so a clean build is usually enough:

sh
ONESIGNAL_DISABLE_LOCATION=true flutter build apk

Two more details close the loop. When using Xcode or Android Studio, the IDE has to be launched from a terminal that has the variable exported, since an IDE started from the Dock or Finder does not inherit variables set only in your shell profile. And on CI, caches for DerivedData, SwiftPM, CocoaPods and Gradle should be keyed on the value of the variable, or skipped for no-location builds, so a restored cache does not resurrect the location module.

That last sentence is the one to copy into your CI configuration.

Platform floor, demo projects, and when to skip the service

The support matrix at the bottom of the README is short: iOS 15 and newer, and tested from Android 4.0.3 at API level 15 up to Android 12.0 at API 31.

That range is worth reading carefully. It says the SDK was tested against Android releases up to 12.0, which is well behind current Android versions, and it is a floor of iOS 15 rather than a recent baseline. A new Flutter project on a current toolchain will usually clear the floor, but a long-lived app supporting older devices is at the edge of what has been verified.

The repository carries a demo project in the /example folder, as the README puts it, and the listing shows several variants: demo, demo-fm, demo-pods, demo-no-location and demo-no-location-pods, plus a flutter-local-notif example and shell scripts for running the demos on iOS and Android. The presence of the no-location variants confirms that the exclusion path is a supported configuration rather than a hack.

Now the alternative. OneSignal's value is that four channels, a dashboard and audience management sit behind one SDK, and in exchange your app talks to a vendor service and your notification data lives there. If your app only needs to send a push notification to its own users, integrating the platform channels directly removes the service, the dashboard and the migration question entirely, at the cost of owning delivery, targeting and analytics yourself. That is more work, but there is no vendor dependency and no parity gap waiting for your next upgrade.

For a team that already has a messaging programme across push, in-app, SMS and email, the SDK is the smaller commitment. For a team with one channel and no plans for the others, it is the larger one.

Editorial conclusion

OneSignal's Flutter SDK fits a Flutter team that wants push, in-app, SMS and email through a single dashboard and a single Dart surface, and that has a staged rollout available on both app stores to de-risk an upgrade. It is the wrong choice for an app that only needs plain platform push and wants no third-party aggregation, since the service, dashboard and SDK add a dependency on the vendor, and it is the wrong choice for a build pipeline that cannot export an environment variable before dependency resolution, because that variable is the only documented way to exclude the native location module. Before upgrading, read MIGRATION_GUIDE.md, decide whether the parity gap in the 5.x user-centric APIs affects your integration, and key your CI caches on the value of ONESIGNAL_DISABLE_LOCATION.

Frequently asked questions

How do I install the OneSignal Flutter SDK?

The README does not include the setup steps and points to the Setup Guide in the OneSignal documentation at documentation.onesignal.com/docs/flutter-sdk-setup. The SDK is published for Flutter iOS and Android apps and supports iOS 15 and newer and Android from API level 15 to 31.

How do I exclude the OneSignal location module from the build?

Export ONESIGNAL_DISABLE_LOCATION=true in the environment before dependencies are resolved, for Swift Package Manager, CocoaPods and Android Gradle builds alike. The value is case-insensitive and 1 is also accepted, and with the module disabled OneSignal.Location calls are ignored on Android and OneSignal.Location.isShared() returns false.

Why does my CocoaPods build fail with Multiple commands produce OneSignalCore.framework?

Because the app target and the extension targets resolve different subspec sets, so CocoaPods creates one pod variant per set and each tries to write the same extracted framework. The README requires the app target and every extension target to request an identical subspec set, which differs depending on whether the location module is disabled.

What changed in the OneSignal Flutter SDK 5.x user-centric APIs?

The README's migration advisory says the new user-centric APIs and v5.x.x SDKs improve user and data management but may not be at 1:1 feature parity with previous versions, and suggests using iOS Phased Rollout or Google Play Staged Rollouts when migrating an existing app. A MIGRATION_GUIDE.md is included in the repository.

Official sources

  1. Issues
  2. OneSignal/OneSignal-Flutter-SDK on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/onesignal-onesignal-flutter-sdk.svg)](https://hysenlabs.com/projects/onesignal-onesignal-flutter-sdk)

Was this useful?