Skip to Content
DocumentationSDKAndroid (Native)

Android SDK (Native Kotlin)

com.appspacer:sdk — Asset OTA updates and crash reporting for native Android apps.

Update model: Google Play prohibits executable code hot-swap for native apps. AppSpacer for Android delivers asset OTA updates — JSON configs, images, data files — that your app reads from the OTA cache at runtime.


Requirements

Minimum
Android minSdk21
compileSdk34
Kotlin1.9+

Installation

Add the library to your module’s build.gradle:

dependencies { implementation 'com.appspacer:sdk:1.0.0' }

Add permissions to AndroidManifest.xml (included automatically if using the AAR):

<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Initialization

Initialize in your Application.onCreate():

import com.appspacer.sdk.AppSpacer import com.appspacer.sdk.AppSpacerConfig class MyApplication : Application() { override fun onCreate() { super.onCreate() AppSpacer.initialize( context = this, config = AppSpacerConfig( apiKey = "your_api_key", appVersion = "1.0.0", ) ) } }

Config Options

PropertyTypeDefaultDescription
apiKeyStringRequiredYour AppSpacer API key
appVersionStringRequiredCurrent app version
updateStrategyUpdateStrategyON_INITON_INIT, BACKGROUND, or MANUAL
debugLoggingBooleanfalseVerbose logcat logging
crashReportingEnabledBooleantrueCapture uncaught exceptions

Reading OTA Assets

Always provide a fallback to your bundled resource:

import com.appspacer.sdk.AppSpacer // In a coroutine: val flags = AppSpacer.readAssetJson("config/feature-flags.json") val showNewUi = flags?.get("new_ui") as? Boolean ?: false // Raw bytes val imageBytes = AppSpacer.readAsset("images/banner.png") // UTF-8 string val csvContent = AppSpacer.readAssetString("data/products.csv")

Manual Update Check

lifecycleScope.launch { val result = AppSpacer.checkForUpdates() when (result.status) { OTAUpdateStatus.UPDATED -> Log.d("OTA", "Updated ${result.updatedCount} asset(s)") OTAUpdateStatus.UP_TO_DATE -> Log.d("OTA", "Already up to date") OTAUpdateStatus.NO_NETWORK -> Log.w("OTA", "Offline") OTAUpdateStatus.FAILED -> Log.e("OTA", result.error ?: "Unknown error") } }

Crash Reporting

Uncaught exceptions are captured via Thread.setDefaultUncaughtExceptionHandler. Pending reports are flushed on next launch.

// Report a handled error try { riskyOperation() } catch (e: Exception) { AppSpacer.reportError(e, context = "PaymentFlow") } // Breadcrumbs AppSpacer.addBreadcrumb("User tapped checkout", category = "navigation") AppSpacer.addBreadcrumb("Cart loaded", category = "data", level = BreadcrumbLevel.INFO)

API Reference

MethodDescription
AppSpacer.initialize(context, config)Initialize — call in Application.onCreate()
AppSpacer.checkForUpdates()suspend — check and download new assets
AppSpacer.readAsset(key)Read cached asset as ByteArray
AppSpacer.readAssetString(key)Read cached asset as String
AppSpacer.readAssetJson(key)Read and parse cached JSON asset
AppSpacer.clearAssetCache()Delete all cached assets
AppSpacer.cacheSize()Total cached bytes
AppSpacer.reportError(throwable)Report a handled error
AppSpacer.addBreadcrumb(message)Add crash context breadcrumb
AppSpacer.sessionIdCurrent session identifier

Backend Integration

GET /api/sdk/android/manifest Headers: x-api-key: <your_api_key> Query: app_version, current_bundle_id, install_id POST /api/sdk/android/report-status Body: { release_id, device_id, app_version, status, error_message }

Send install_id (a stable per-device ID) on every manifest call — it is required for staged-rollout targeting and monthly active-user metering. Report installed/failed back to report-status so egress is billed once per device and failed installs can trigger auto-rollback.

Upload asset bundles from the dashboard with --platform android.

Last updated on