OneSignal Flutter SDK

repository·main·Indexed 20 days ago

https://github.com/onesignal/onesignal-flutter-sdk

A unified SDK for integrating email, SMS, push notifications, and in-app messaging into Flutter applications for iOS and Android. Includes documentation on configuring App IDs via .env, managing iOS launch screen assets, and disabling the native location module using the ONESIGNAL_DISABLE_LOCATION flag to reduce app footprint and avoid unnecessary permission requests.

Tokens
11.2K
Snippets
36
Records
51
Agent score
70%

What's inside onesignal-flutter-sdk

  1. Explore the OneSignal Flutter Sample App structure

    main

    The examples/demo/ directory provides a comprehensive reference implementation of how to integrate the OneSignal Flutter SDK into a production-grade application. The structure follows a clean architecture pattern, separating concerns into services, viewmodels, and UI components.

    Key architectural layers in the sample include:

    • Services: Handles OneSignal API interactions (onesignal_api_service.dart), local preferences (preferences_service.dart), and UI helpers (tooltip_helper.dart).
    • ViewModels: Manages application state (app_viewmodel.dart).
    • Screens & Widgets: Organized by feature (e.g., push_section.dart, in_app_section.dart, tags_section.dart) to demonstrate specific SDK capabilities like Push Notifications, In-App Messages, Tags, and Custom Events.
  2. Understand device-scoped users and identity

    main

    A device-scoped user is an anonymous user with no aliases. Upon app installation, the OneSignal SDK is initialized with a device-scoped user.

    To upgrade a device-scoped user to an identified user, call OneSignal.login("USER_EXTERNAL_ID") using a unique external user ID. This allows the user to be retrieved via the OneSignal dashboard and associated with specific identities.

  3. Important SDK limitations and constraints

    main

    When working with the OneSignal Flutter SDK, keep the following constraints in mind:

    • Initialization Order: Any calls to the OneSignal.User namespace (e.g., OneSignal.User.addTag("tag", "2")) must be invoked after the SDK has been initialized.
    • App IDs: Changing app IDs is not supported.
    • User State Refresh: The user state is only refreshed from the server during a new session (cold start or when the app has been in the background for over 30 seconds) or when the user is logged in. This is intended behavior.
  4. Verify No-Location configuration on iOS

    main

    When building with ONESIGNAL_DISABLE_LOCATION=true, the following occurs on iOS:

    • The native location module is excluded from the build.
    • The app does not require NSLocationWhenInUseUsageDescription or NSLocationAlwaysAndWhenInUseUsageDescription in the Info.plist.
    • The project still includes OneSignalNotificationServiceExtension and OneSignalWidgetExtension via Swift Package Manager.
    • On iOS 16.2+, you can test the sample widget using the app's Start Live Activity button.
  5. How iOS compatibility is handled for local and push notifications

    main

    This project demonstrates how to make onesignal_flutter and flutter_local_notifications coexist on iOS.

    To ensure both notification delegates work correctly:

    1. Initialization Order: The app initializes flutter_local_notifications before OneSignal. This allows both delegates to coexist.
    2. AppDelegate Configuration: The AppDelegate.swift is configured to preserve the foreground presentation options provided by flutter_local_notifications. This ensures that local banners, sounds, and list entries continue to function correctly even after OneSignal installs its notification center delegate.
  6. Understand the User-Centered Model (v5.x.x)

    main

    In OneSignal SDK v5.x.x, the model has shifted from device-centered (using 'players') to user-centered. This allows for omni-channel integration across devices.

    Key concepts:

    • Users: Represents your end-user. A user can have zero or more subscriptions and can be identified by one or more aliases. Users can also have data tags for attribution.
    • Subscriptions: The method by which a user receives communications (Push, SMS, Email). A single user can own multiple subscriptions. The subscription_id (formerly player_id) uniquely identifies a communication channel.
    • Aliases: Key-value pairs used to identify a user within your application. The alias label is the key (e.g., external_id), and the alias id is the value specific to that user. OneSignal uses a built-in label external_id which is used when calling OneSignal.login().
  7. Disable OneSignal Location module

    main

    If your application does not require location services, you can exclude the native OneSignal location module from iOS and Android builds to reduce footprint.

    To do this, set the environment variable ONESIGNAL_DISABLE_LOCATION=true (or 1) before resolving dependencies or building.

    Behavioral changes when disabled:

    • On Android, calls to OneSignal.Location are ignored.
    • OneSignal.Location.isShared() will return false on all platforms.

    Note for CI (GitHub Actions): You can set this at the job or step level:

    env:
      ONESIGNAL_DISABLE_LOCATION: true
  8. Customize iOS launch screen assets

    main

    To change the launch screen image for the iOS version of your Flutter application, you can either replace the image files directly in the project directory or use Xcode.

    Option 1: Direct File Replacement Replace the existing image files located in the examples/demo-fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory with your own assets.

    Option 2: Using Xcode

    1. Open your Flutter project's iOS workspace by running open ios/Runner.xcworkspace in your terminal.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Locate the LaunchImage asset set and drag and drop your new images into it.
    open ios/Runner.xcworkspace
  9. Install iOS Dependencies for OneSignal

    main

    To ensure the CocoaPods and Xcode configurations are correctly generated, follow this specific sequence:

    1. Run flutter pub get to generate the Generated.xcconfig file required by the Podfile.
    2. Navigate to the ios directory and run pod install.
    3. Open the .xcworkspace file in Xcode for all subsequent development (do not use .xcodeproj).
    flutter pub get
    cd ios && pod install
  10. Set up the OneSignal Notification Service Extension

    main

    The Notification Service Extension allows OneSignal to process notifications (such as rich media or badges) before they are displayed.

    1. NotificationService.swift

    Create this file within the OneSignalNotificationServiceExtension/ directory. It uses OneSignalExtension to handle the notification lifecycle.

    2. Info.plist

    Ensure the extension has a valid Info.plist with the correct NSExtensionPointIdentifier set to com.apple.usernotifications.service.

    3. Entitlements

    The OneSignalNotificationServiceExtension.entitlements file must contain an App Group that matches the one defined in your main Runner.entitlements.

    // OneSignalNotificationServiceExtension/NotificationService.swift
    import UserNotifications
    import OneSignalExtension
    
    class NotificationService: UNNotificationServiceExtension {
        var contentHandler: ((UNNotificationContent) -> Void)?
        var receivedRequest: UNNotificationRequest!
        var bestAttemptContent: UNMutableNotificationContent?
    
        override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
            self.receivedRequest = request
            self.contentHandler = contentHandler
            self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    
            if let bestAttemptContent = bestAttemptContent {
                OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler)
            }
        }
    
        override func serviceExtensionTimeWillExpire() {
            if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
                OneSignalExtension.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent)
                contentHandler(bestAttemptContent)
            }
        }
    }