Skip to Content

Flutter

Flutter plugin that wires the native Zing SDK on Android and iOS (and provides a Dart-facing API for initialization, logout, and launching native screens).

Current platform support

The Flutter plugin currently supports Android and iOS.

PlatformStatusNotes
AndroidFully SupportedAll features
iOSFully SupportedAll features except WorkoutPlanCard

Requirements

RequirementValue / Notes
Flutter3.3.0+
Android minSdk26 (Android 8.0)
Android compileSdk34+
Dependency injection (Android)Hilt
Maven credentials (Android native SDK)GitHub Packages token
iOS minimum version16.0

Install the plugin

Add the Git dependency to your pubspec.yaml (the plugin is distributed privately and is not published on pub.dev):

dependencies: zing_sdk_initializer: git: url: https://github.com/Muze-Fitness/fitness-coach-sdk-flutter.git

Then run flutter pub get.

Android setup

To integrate on Android, you must configure your project to support the native Zing SDK dependencies (Hilt + GitHub Packages).

Add Maven repository & credentials

Add the GitHub Packages repository to your Android build (project-level android/build.gradle or settings.gradle):

maven { url = uri("https://maven.pkg.github.com/Muze-Fitness/fitness-coach-sdk-android") val localProperties = java.util.Properties() val localPropertiesFile = File(rootDir, "local.properties") if (localPropertiesFile.exists()) { localProperties.load(localPropertiesFile.inputStream()) } credentials { username = localProperties.getProperty("zing_sdk_username") password = localProperties.getProperty("zing_sdk_token") } }

Ensure your local.properties contains your credentials:

zing_sdk_username=GITHUB_USERNAME zing_sdk_token=ghp_xxx_with_read_packages

Configure Hilt (KSP or KAPT)

The native SDK uses Hilt for dependency injection.

  • Option A: KSP (recommended)
// Project-level (android/build.gradle or settings.gradle) id("com.google.dagger.hilt.android") version "2.56.1" apply false id("com.google.devtools.ksp") version "2.1.20-2.0.0" apply false
// App module (android/app/build.gradle) plugins { id("com.google.devtools.ksp") id("com.google.dagger.hilt.android") } dependencies { implementation("com.google.dagger:hilt-android:2.56.1") ksp("com.google.dagger:hilt-android-compiler:2.56.1") }
  • Option B: KAPT (legacy projects)
// Project-level (android/build.gradle or settings.gradle) id("com.google.dagger.hilt.android") version "2.56.1" apply false
// App module (android/app/build.gradle) plugins { kotlin("kapt") id("com.google.dagger.hilt.android") } dependencies { implementation("com.google.dagger:hilt-android:2.56.1") kapt("com.google.dagger:hilt-android-compiler:2.56.1") }

Custom Application class

Create an Application class extending SdkApplication and annotate it with @HiltAndroidApp:

import coach.zing.fitness.coach.SdkApplication import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp class MyApplication : SdkApplication()

Register it in AndroidManifest.xml:

<application android:name=".MyApplication" ... >

Update MainActivity

Change MainActivity to inherit from FlutterFragmentActivity and add @AndroidEntryPoint:

import dagger.hilt.android.AndroidEntryPoint import io.flutter.embedding.android.FlutterFragmentActivity @AndroidEntryPoint class MainActivity : FlutterFragmentActivity()

Disable the default WorkManager initializer

Add the following provider override inside <application> in AndroidManifest.xml:

<provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <meta-data android:name="androidx.work.WorkManagerInitializer" android:value="androidx.startup" tools:node="remove" /> </provider>

Health Connect (optional)

If you enable Health Connect synchronization, add the following permissions:

<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

To restart health sync after reboot, register the boot receiver inside <application>:

<receiver android:name="coach.zing.fitness.coach.broadcast.SdkHealthSyncBootReceiver" android:exported="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>

Initialization

Initialize the SDK from Dart during app startup. You need to provide an authentication configuration during initialization.

API Key

Use this mode when backend integration is not available:

import 'package:zing_sdk_initializer/zing_sdk_initializer.dart'; await ZingSdk.instance.init( SdkAuthentication.apiKey( ios: 'your-ios-api-key', android: 'your-android-api-key', ), );

External Token

Use this mode when your backend manages user authentication and issues JWT tokens.

import 'package:zing_sdk_initializer/zing_sdk_initializer.dart'; await ZingSdk.instance.init( SdkAuthentication.externalToken(yourTokenCallback), );

Implement the AuthTokenCallback interface.

abstract interface class AuthTokenCallback { /// Called when SDK needs an authentication token /// Return a valid JWT containing a `sub` claim with the partner user ID. Future<String> getAuthToken(); /// Called when the current token is no longer valid. void onTokenInvalid(); }

Initialization errors

CodeDescription
already_initializedCalled init() more than once
native_init_failedNative SDK failed to initialize (invalid auth config or internal error)

Login

After initialization, call login() to authenticate the user and start a session:

await ZingSdk.instance.login();

Call login() only on the first session, when the auth state is SdkAuthStateLoggedOut. On subsequent sessions, init() automatically restores the previous session — you do not need to call login() again.

Login errors

CodeDescription
not_initializedSDK has not been initialized yet
login_failedLogin failed (already logged in, login already in progress, or token retrieval failed)

Logout

Logout and clear the user session.

await ZingSdk.instance.logout();

Logout errors

CodeDescription
not_initializedSDK has not been initialized yet
logout_failedLogout failed (no active session)

Auth State

Monitor authentication state changes via the authState stream:

ZingSdk.instance.authState.listen((state) { switch (state) { case SdkAuthStateLoggedOut(): // User is not authenticated case SdkAuthStateInProgress(): // Authentication is in progress case SdkAuthStateAuthenticated(): // User is authenticated } });

Launch native screens

await ZingSdk.instance.openScreen(AiAssistantRoute());

Supported routes:

  • HomeRoute()
  • CustomWorkoutRoute()
  • AiAssistantRoute()
  • WorkoutPlanDetailsRoute()
  • FullScheduleRoute()
  • ProfileSettingsRoute()

Launch screen errors

CodeDescription
not_initializedSDK has not been initialized yet
missing_routeNo route argument provided
unknown_routeUnrecognized route identifier
no_activityNo activity or root view controller available to present the screen
launch_failedScreen launch failed

Notes

  • Configure auth/tokens as described in Authorization before launching UI.
Last updated on