bubbl_flutter_sdk 5.0.0-alpha.1 copy "bubbl_flutter_sdk: ^5.0.0-alpha.1" to clipboard
bubbl_flutter_sdk: ^5.0.0-alpha.1 copied to clipboard

Bubbl for Flutter - geofenced and scheduled notifications, surveys and analytics, bridging the native Bubbl SDKs.

Bubbl for Flutter #

Geofenced and scheduled notifications, surveys and analytics, as a thin bridge over the native Bubbl SDKs. Everything (geofences, notifications, the event queue, consent) runs in the native SDK, which keeps working with the app closed; Dart calls it and hears from it. The functions are the native SDKs' own: see docs/PUBLIC_API.md.

5.0 pre-release, on Android and iOS alike.

Install #

Needs Flutter 3.32 or later. Installs on Android 6 (API 23) and iOS 13, and works on Android 8.1 (API 27) and iOS 17 and later; on older versions every call does nothing, safely, and await Bubbl.isSupported is false. So a new app needs no minimum-version changes.

  1. Add the package:

    dependencies:
      bubbl_flutter_sdk: ^5.0.0-alpha.1
    

    or flutter pub add bubbl_flutter_sdk:^5.0.0-alpha.1. 5.0 is a pre-release, so name the version: a plain flutter pub add bubbl_flutter_sdk picks the latest stable release, 4.x, a different SDK. ^5.0.0-alpha.1 takes later 5.0 pre-releases and 5.0.0 itself as they come.

  2. Start Bubbl at launch:

    import 'package:bubbl_flutter_sdk/bubbl_flutter_sdk.dart';
    
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Bubbl.start(apiKey: 'pk_live_…', options: const BubblOptions(baseUrl: 'https://…'));
      runApp(const MyApp());
    }
    
  3. iOS:

    • in ios/Runner/Info.plist, NSLocationWhenInUseUsageDescription and NSLocationAlwaysAndWhenInUseUsageDescription (what the location prompts say);
    • the Push Notifications capability (Runner target › Signing & Capabilities), for Bubbl's pushes.

    Swift Package Manager (Flutter's default) and CocoaPods both work: the plugin carries the Bubbl iOS SDK itself, so there's no separate pod or package to add.

That's all. When the OS wakes the app for a geofence or a push, the native SDK starts itself from what it saved, before any Dart runs.

Before publishing to Google Play: the SDK declares background location (ACCESS_BACKGROUND_LOCATION, for geofences with the app closed), so Play asks for the location permissions declaration in the Play Console.

Background refresh (iOS, optional) #

Without it, Bubbl sends what's queued when the app goes to the background and on its next run. With it, iOS wakes the app now and then and Bubbl sends it then. In ios/Runner/Info.plist:

<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
	<string>tech.bubbl.sdk.refresh</string>
</array>
<key>UIBackgroundModes</key>
<array>
	<string>fetch</string>
</array>

(If the app already has either key, add the value to its array.) Bubbl registers the task itself at launch, before any Dart runs; with only one of the two, it doesn't.

Pictures on pushes (iOS, optional) #

iOS shows a push's picture only through a notification service extension in the app:

  1. In Xcode, File › New › Target › Notification Service Extension (named NotificationService here), with the same Minimum Deployments as the app.

  2. Replace the extension's NotificationService.swift with:

    import BubblNotificationService
    
    class NotificationService: BubblNotificationService {}
    
  3. In ios/Podfile, after the Runner target:

    target 'NotificationService' do
      use_frameworks! :linkage => :static
      pod 'BubblFlutterNotificationService', :path => '.symlinks/plugins/bubbl_flutter_sdk/ios'
    end
    

    (use_frameworks! because Flutter's Runner target has it, and CocoaPods wants an extension and its app to agree; static, so there's nothing for the app to embed.)

    This works with Swift Package Manager on too: Flutter installs pods whenever the app has a Podfile. An app on Swift Package Manager with no ios/Podfile gets Flutter's first:

    1. turn Swift Package Manager off: flutter config --no-enable-swift-package-manager;
    2. flutter build ios once, which writes ios/Podfile;
    3. turn it back on: flutter config --enable-swift-package-manager (the Podfile stays, and Flutter keeps running pod install for it);
    4. add the NotificationService target block above to it.
  4. In Xcode, the Runner target › Build Phases: drag "Embed Foundation Extensions" above "Thin Binary", or Xcode reports a dependency cycle.

examples/flutter-wrapper has this extension, built by CI both ways.

Bubbl's pushes then show their picture; anything else passes through untouched. An app with its own extension work can override didReceive and call super for Bubbl's pushes only (BubblNotificationService.isBubbl(request)).

Using it #

await Bubbl.permissions.requestLocation(always: true); // the privacy view first, if the dashboard says so
await Bubbl.setSegments(['vip']);
await Bubbl.track('purchase.completed', {'total': 12.5});

final subscription = Bubbl.addEventListener((event) {
  if (event is BubblGeofenceEntered) print('Entered ${event.locationId}');
});

// Draw notifications yourself while the app is open (Bubbl still shows them in the background):
await Bubbl.setNotificationListener((message) async {
  showMyCard(message); // then Bubbl.reportDisplayed(message), reportCtaClicked, submitSurvey…
  return true;         // false: Bubbl shows it
});

final diagnostics = await Bubbl.diagnostics();

Consent (requireConsent, setConsent, optOut, deleteMyData), setLocationEnabled, present, the report* functions, submitSurvey, openCta and isBubblMessage are as in docs/PUBLIC_API.md.

An app that gets its device credential elsewhere (installs provisioned ahead of time, its own pairing flow) starts with it instead of an API key, the same way at every launch; the device never registers itself:

await Bubbl.startWithCredential(
  BubblCredential(keyId: keyId, secret: secret, installId: installId),
  options: const BubblOptions(baseUrl: 'https://…'),
);

If the server refuses it, Bubbl stops, with a BubblCredentialRejected event and credentialRejected in diagnostics, until it's started with a new one.

The one difference from the native SDKs: the notification listener is asked only while the app's Flutter screen is in front (Android: its Flutter activity; iOS: the app active). Otherwise Bubbl shows the notification itself: its own screen if the app is in front (behind a native screen or a permission dialog, say), a system notification if not. A notification Dart can't take (after a hot restart, until the listener is set again) is shown by Bubbl too, never dropped.

From 4.x #

5.0 is a new SDK against Bubbl's device API v1, not an update: there's no compatibility layer, and 4.x's data on the device isn't carried over (the install registers as new).

4.x 5.0
BubblSdk.instance.boot(BubblConfig(apiKey, environment, runtimeBaseUrl, ingestBaseUrl, …)) Bubbl.start(apiKey:, options: BubblOptions(baseUrl:)): one base URL, no environments
startLocationTracking, refreshGeofence, handleLocationUpdate, refresh, flush Gone: the SDK watches geofences, sends and refreshes by itself
registerPushToken, handleFirebasePayload, handleNotificationPayload, showNotification Gone: the SDK takes the push token and handles Bubbl's pushes itself (isBubblMessage tells yours apart)
setDefaultNotificationModalEnabled, modal styles, notificationRenderingMode setNotificationListener: return true to draw it yourself, then report*; present shows Bubbl's card
updateSegments, track(BubblTrackEvent), submitSurveyResponse setSegments, track(name, properties), submitSurvey(message, answers)
events (map-based) Bubbl.events / addEventListener: typed BubblEvents
(none) Consent, permissions (with the dashboard's privacy view), setLocationEnabled, deleteMyData

Android #

  • minSdk 23 (Bubbl works from API 27; below it, calls do nothing). Depends on tech.bubbl.sdk:bubbl-sdk (Maven Central).
  • The plugin applies the Kotlin Gradle plugin only when the app has no Kotlin of its own: AGP 9's built-in Kotlin, or the plugin Flutter 3.44+ applies, is used as it is. So it builds, without Flutter's warning about plugins applying KGP, on older and newer Flutter alike.
  • Push: the SDK handles Bubbl's FCM pushes itself, alongside any Firebase messaging the app has.

Working on the plugin #

The iOS SDK's sources are copied into the plugin from renewed-sdk/ios (not kept twice in git). Before building for iOS or publishing, from flutter/:

dart run tool/sync_ios_sources.dart

Then flutter analyze && flutter test, and the example in examples/flutter-wrapper.

An app can use a checkout instead of pub.dev: bubbl_flutter_sdk: { path: ../renewed-sdk/flutter }, with the sync above run once. If the native Android SDK's version isn't on Maven Central, build against a local copy: ./gradlew publishToMavenLocal in renewed-sdk/android, and mavenLocal() in the app's repositories (allprojects { repositories { … } } in android/build.gradle.kts, as examples/flutter-wrapper does).

0
likes
160
points
211
downloads

Documentation

API reference

Publisher

verified publisherbubbl.tech

Weekly Downloads

Bubbl for Flutter - geofenced and scheduled notifications, surveys and analytics, bridging the native Bubbl SDKs.

Homepage

Topics

#notifications #geofencing #location #push-notifications #analytics

License

Apache-2.0 (license)

Dependencies

flutter

More

Packages that depend on bubbl_flutter_sdk

Packages that implement bubbl_flutter_sdk