Android
Native Android toolkit that integrates the Zing Fitness experience into your app. The SDK ships as an AAR (coach.zing:fitness-sdk) consumable via GitHub Packages.
Requirements
| Requirement | Value / Notes |
|---|---|
| Minimum Android version | 8.0 (API 26) |
| Compile SDK | 34+ |
| Kotlin | 2.1.0 |
| Dependency injection | Hilt (com.google.dagger:hilt-android) |
| Maven credentials | GitHub Packages PAT with read:packages |
Setup
Add the GitHub Packages Repository
Add the following to your settings.gradle or top-level build.gradle:
// settings.gradle or top-level build.gradle
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/Muze-Fitness/fitness-coach-sdk-android")
val localProperties = java.util.Properties()
val file = File(rootDir, "local.properties")
if (file.exists()) {
localProperties.load(file.inputStream())
}
credentials {
username = localProperties.getProperty("sdk_maven_read_username")
?: System.getenv("GITHUB_USER")
password = localProperties.getProperty("sdk_maven_read_token")
?: System.getenv("GITHUB_TOKEN")
}
}
}
}Create local.properties next to your top-level settings.gradle if it does not exist yet and provide the credentials:
sdk_maven_read_username=GITHUB_USERNAME
sdk_maven_read_token=ghp_xxx_with_read_packagesDeclare the Dependency
dependencies {
implementation("coach.zing:fitness-sdk:<latest-version>")
}Replace <latest-version> with the version published in GitHub Packages (e.g. 1.0.5).
Enable Hilt
Add the Hilt plugin and dependencies to your app-level build.gradle:
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.dagger.hilt.android")
kotlin("kapt") // or id("com.google.devtools.ksp")
}
dependencies {
implementation("com.google.dagger:hilt-android:2.56.1")
kapt("com.google.dagger:hilt-android-compiler:2.56.1")
// ksp("com.google.dagger:hilt-android-compiler:2.56.1")
}Create an Application Subclass
Create an Application subclass that extends SdkApplication:
@HiltAndroidApp
class FitnessApp : SdkApplication()Register it in AndroidManifest.xml:
<application
android:name=".FitnessApp"
... />Initialization & Authentication
The SDK follows a three-step lifecycle: init() → login() → logout().
init(sdkAuth)— configure the authentication method (call once).login()— start a session (must be called afterinitonly when session is not logged in — checkSdkAuthState.LoggedOut).logout()— end the session and clear user data.
Authentication methods
| Method | Class | Description |
|---|---|---|
| Partner Key | SdkAuthentication.ApiKey | Simple API key authentication |
| Partner Token | SdkAuthentication.ExternalToken | Token-based auth with partner’s own backend |
Initialization
Partner Key — pass your API key directly:
ZingSdk.init(SdkAuthentication.ApiKey(apiKey = "your-api-key"))Partner Token — implement AuthTokenCallback to provide and refresh tokens:
ZingSdk.init(
SdkAuthentication.ExternalToken(
authTokenCallback = object : AuthTokenCallback {
override suspend fun getAuthToken(): String {
return yourAuthRepo.getToken()
}
override fun onTokenInvalid() {
// handle invalid token, e.g. refresh or re-authenticate
}
}
)
)Note:
getAuthToken()is a suspend function called by the SDK whenever it needs a valid token.onTokenInvalid()is called when the current token is rejected.
Login
suspend fun login()Must be called after init() when authState is SdkAuthState.LoggedOut.
Throws SdkAlreadyLoggedInException if the user is already logged in.
Auth state monitoring
Observe ZingSdk.authState: StateFlow<SdkAuthState> to react to authentication
changes:
| State | Description |
|---|---|
SdkAuthState.LoggedOut | No active session |
SdkAuthState.InProgress | Login is in progress |
SdkAuthState.Authenticated | Session active |
Logout
suspend fun logout()Ends the current session. Throws SdkAlreadyLoggedOutException if the user is
already logged out.
Full example
class FitnessApp : SdkApplication() {
override fun onCreate() {
super.onCreate()
ZingSdk.init(SdkAuthentication.ApiKey(apiKey = "your-api-key"))
}
}
// Start a session (e.g. in your Activity or ViewModel)
fun onStart(scope: CoroutineScope) {
scope.launch {
if (ZingSdk.authState.value is SdkAuthState.LoggedOut) {
ZingSdk.login()
}
}
}
// End the session
fun onLogout(scope: CoroutineScope) {
scope.launch {
ZingSdk.logout()
// e.g. navigate to login or clear user data
}
}Launching Zing Screens
You can open any major Zing screen explicitly via
ZingSdkActivity.launch(context, StartingRoute.<Destination>). Supported
destinations include:
StartingRoute.HomeStartingRoute.CustomWorkoutStartingRoute.AiAssistantStartingRoute.WorkoutPlanDetailsStartingRoute.FullScheduleStartingRoute.ProfileSettings
Example
button.setOnClickListener {
ZingSdkActivity.launch(this, StartingRoute.AiAssistant)
}Health Connect (optional)
The SDK can show a Health Connect permissions screen and run background Health Connect sync.
Permissions
Add the following to your host app AndroidManifest.xml:
<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" />Boot receiver (restart 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>Health Connect permissions screen
ZingSdkActivity.launch(context, StartingRoute.HealthConnectPermissions)