Flutter SDK Lifecycle

This page covers how the Magify Flutter SDK starts up, tracks sessions, and keeps its remote configuration in sync over the life of your app.

Initialization

Everything goes through the MagifyClient singleton, reached through MagifyClient.instance. Call init once, as early as possible during startup, and await it before making any other call:

await MagifyClient.instance.init(
  const MagifyConfig(
    applicationName: 'MyApplication',
    defaultConfig: 'assets/magify_default_config.json',
    isSandbox: false,
  ),
);

Calling init more than once is safe: later calls return the future of the first call and do not create a second client instance — the config passed to those later calls is ignored. A failed call is not cached, so the next call retries the initialization. A failure throws MagifyException.

bool get isInitialized reports whether init has completed successfully. It is synchronous — use it for guard checks, not as a substitute for awaiting init.

Sessions

The SDK tracks how many times the app has been launched. You do not need to send an app-launch event yourself — the SDK sends it automatically, once per session, as part of init.

MagifyClient.instance.sessionNumberChanges.listen((sessionNumber) {
  debugPrint('Session started: $sessionNumber');
});

Remote configuration

The SDK downloads a remote config on init and keeps it available for features, storedFeatures and content to read.

MagifyClient.instance.configLoaded.listen((_) {
  // Feature flags, stored features and content are safe to re-read now.
});

await MagifyClient.instance.update();

Call update() whenever your app wants a fresher config on demand — for example when it returns to the foreground — rather than waiting for the SDK's own scheduled refresh.

Context sync time

Future<ContextSyncTime?> get contextSyncTime returns the clock offset between the device and the Magify backend, as measured during the last context sync. It is null until the first sync has completed.

final syncTime = await MagifyClient.instance.contextSyncTime;
if (syncTime != null) {
  debugPrint('Device/backend clock offset: ${syncTime.offset}');
}

Use offset when your app needs backend-accurate timestamps (for example, time-limited offers) but only has the device clock available.

Resetting local state

Future<void> resetState() drops locally-held client state — counters, trackers and cached campaigns — and then reloads the remote config. Treat it as a development/debugging helper, not a user logout.

Platform difference: on iOS, resetState() also sends a fresh app-launch event and resets the session counter back to 1; on Android it resets and reloads the config without touching the session counter. Keep this in mind if your app or your tests read sessionNumber right after calling resetState().

await MagifyClient.instance.resetState();

Errors

A failed SDK call throws MagifyException, carrying code, message and details. Model constructors (and a couple of validation calls, like setPurchaseVerificationPolicy) throw ArgumentError instead, for input that's invalid before the call is even made.

Next step

Now that you understand initialization, sessions and config refresh, continue to Privacy to configure logging, GeoIP resolution and authorization status.

Related articles

AdvertiserService

Flutter SDK Configuration

Flutter SDK Configuration options

AppsFlyer

Android SDK Privacy & Consent

Advanced