# Android

Install the Kotlin source module, configure Gradle, and deliver app events without blocking the UI thread.

## Prerequisites

- An Aplyna application with its SDK key.
- Android API 23 or newer, compile SDK 35 and JDK 17.
- A Gradle project compatible with the supplied Android/Kotlin plugins. The source module declares AGP 8.9.1 and Kotlin 2.1.20.

> **Code-first SDK**
> The Android source client supports events, assignments and schema-v1 configuration. It does not include a visual phone-screen renderer or Google Play Billing implementation.

## 1. Add the source module

- [Download Kotlin SDK](https://aplyna.com/downloads/aplyna-android.zip): ZIP containing the Android library module and manifest.

1. Extract the archive and copy sdks/android into your Android project as aplyna-sdk.
2. Include the module in your root settings.gradle.kts.
3. Add the project dependency to your app module.
4. Align plugin declarations with your root project's plugin management. Avoid declaring conflicting plugin versions twice; resolve Android and Kotlin plugins through your existing build setup.
5. Sync Gradle and build the app.

### settings.gradle.kts · add to existing settings

```
include(":aplyna-sdk")
```

### app/build.gradle.kts · dependencies

```
dependencies {
    implementation(project(":aplyna-sdk"))
}
```

## 2. Import the client

### Kotlin

```
import com.aplyna.sdk.AplynaClient
```

The library manifest includes android.permission.INTERNET. Inspect the merged app manifest if network access fails. Resolve Gradle errors before proceeding to runtime configuration.

## 3. Configure an installation

### Kotlin · background execution

```
import com.aplyna.sdk.AplynaClient
import java.util.UUID

val prefs = context.getSharedPreferences("aplyna", 0)
val installationId = prefs.getString("installation_id", null)
    ?: UUID.randomUUID().toString().also {
        prefs.edit().putString("installation_id", it).apply()
    }
val client = AplynaClient(
    baseUrl = "https://aplyna.com",
    apiKey = "YOUR_APP_SDK_KEY",
    installationId = installationId,
    storageDirectory = context.filesDir
)

// After consent; call networking methods off the main thread.
client.setConsent(true)
client.track(name = "app_opened")
client.flush()
```

> **Keep network work off the main thread**
> flush, assignment and configuration use blocking network calls with ten-second connection/read timeouts. Call them on your existing executor or IO dispatcher. The SDK does not bundle kotlinx.coroutines.

## 4. Deliver from a background executor

### Kotlin · using the Java standard library

```
val executor = java.util.concurrent.Executors.newSingleThreadExecutor()
executor.execute {
    try {
        client.flush()
    } catch (error: Exception) {
        // Surface a diagnostic without logging credentials.
        // Retain the client and retry delivery later.
    }
}
// Shut down the executor when its owning integration is disposed.
```

Use application-owned storage, such as context.filesDir, for the queue and caches. Reuse one client and a persisted installation ID. setConsent(false) clears queued events. Configure a later flush attempt after a final network failure; retries are bounded.

## Next steps

- [Existing onboarding](https://aplyna.com/docs/existing-onboarding): Track native Android steps and server assignments.
- [Event reference](https://aplyna.com/docs/events): Payloads, timestamps and deduplication.
- [Configuration compatibility](https://aplyna.com/docs/configuration): Schema v1 and unsupported visual layouts.
