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

Requirements

RequirementValue / Notes
Flutter3.3.0+
Android minSdk26 (Android 8.0)
Android compileSdk36+
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 ref: v1.0.0

Check the GitHub releases page  for the latest available version.

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>

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( authentication: 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( authentication: 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)

Configuration

Pass an SdkConfiguration to customize SDK behavior:

await ZingSdk.instance.init( authentication: ..., configuration: SdkConfiguration( coachesAvailability: CoachesAvailability.userGenderBased, genderAvailability: GenderAvailability.binary, ), );
FieldTypeDefaultDescription
coachesAvailabilityCoachesAvailabilityallCoachesallCoaches — all coaches are shown; userGenderBased — only coaches matching the user’s gender.
genderAvailabilityGenderAvailabilityallall — all gender options; binary — male/female only.

Theme

Pass an SdkTheme to apply branding overrides. Any unset field falls back to SDK defaults.

await ZingSdk.instance.init( authentication: ..., theme: SdkTheme( colors: SdkColors( brandPrimary: Color(0xFF1A73E8), brandSecondary: Color(0xFF34A853), ), cornersRounding: SdkCornerRounding( buttonBorder: SdkRadius.pill(), ), typography: SdkTypography( brand: 'YourBrandFont', system: 'YourSystemFont', ), ), );
FieldTypeDescription
colorsSdkColorsOverrides brand, text, button and background colors.
cornersRoundingSdkCornerRoundingOverrides button border radius. Use SdkRadius.value(n) for a fixed radius or SdkRadius.pill() for a pill shape.
typographySdkTypographyOverrides font families for brand and system text.

Theming

Working with themes

Use the theming playground to interactively preview how colors, typography, corner rounding, and images look in the SDK screens before writing any code.

Pass a fully composed SdkTheme to customize all visual aspects of the SDK. Every field is optional — any unset field falls back to the SDK default.

await ZingSdk.instance.init( authentication: ..., theme: SdkTheme( colors: SdkColors( brandPrimary: Color(0xFF1A73E8), brandSecondary: Color(0xFF34A853), textHeadingDarkPrimary: Color(0xFF1D212C), textHeadingLightPrimary: Color(0xFFFFFFFF), textBodyDarkPrimary: Color(0xFF1D212C), textBodyDarkSecondary: Color(0xFF6B7280), buttonPrimary: Color(0xFF1A73E8), buttonSecondary: Color(0xFF34A853), bgPrimary: Color(0xFFFFFFFF), bgSecondary: Color(0xFFF3F4F6), ), cornersRounding: SdkCornerRounding( buttonBorder: SdkRadius.pill(), ), typography: SdkTypography( brand: 'YourBrandFont', system: 'YourSystemFont', ), ), );

Working with pictures

The SDK automatically loads custom images from the host app’s platform resources using fixed asset names. No Flutter-level code is required — just add the images with the correct names to your platform project.

Android

Add drawable files to android/app/src/main/res/drawable/. For best quality, provide density-specific variants — Android will automatically pick the correct one for the device screen:

res/ drawable-mdpi/zing_welcome_picture.png drawable-hdpi/zing_welcome_picture.png drawable-xhdpi/zing_welcome_picture.png drawable-xxhdpi/zing_welcome_picture.png drawable-xxxhdpi/zing_welcome_picture.png
Drawable nameUsed for
zing_plan_backgroundPlan section background image
zing_welcome_pictureWelcome screen illustration
zing_coach_johnCoach John avatar
zing_coach_jenniferCoach Jennifer avatar
zing_coach_sarahCoach Sarah avatar
zing_coach_chrisCoach Chris avatar

iOS

Add image assets to Assets.xcassets using the same names:

Asset nameUsed for
zing_plan_backgroundPlan section background image
zing_welcome_pictureWelcome screen illustration
zing_coach_johnCoach John avatar
zing_coach_jenniferCoach Jennifer avatar
zing_coach_sarahCoach Sarah avatar
zing_coach_chrisCoach Chris avatar
zing_coach_manelCoach Manel avatar
zing_coach_adrianaCoach Adriana avatar

All image names are optional — the SDK falls back to its built-in assets for any name that is not found.

Working with typography

Pass SdkTypography inside SdkTheme to override the SDK’s built-in fonts. Two font roles are available:

FieldApplies toDefault
brandHeadings, display text, counter, coach nameSDK built-in (Outfit)
systemBody text, UI elements, coach chatSDK built-in (SF Pro / Roboto)

Both fields are optional — omitting a field keeps the SDK’s built-in font for that role.

The value must be the name the font is registered under in the host app’s platform resources. Register your font first, then pass the same name to SdkTypography:

PlatformHow to registerName to pass
AndroidPlace .ttf/.otf in android/app/src/main/res/font/Filename without extension (e.g. "inter")
iOSAdd the font file to Xcode and declare it under UIAppFonts in Info.plistPostScript family name (e.g. "Inter")
await ZingSdk.instance.init( SdkAuthentication.apiKey( ios: 'your-ios-api-key', android: 'your-android-api-key', ), theme: SdkTheme( typography: SdkTypography( brand: 'MyBrandFont', // registered as res/font/mybrandfont.ttf on Android system: 'MySystemFont', // registered as PostScript name on iOS ), ), );

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