> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appdna.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Android API Reference

> Complete method reference for AppDNA Android SDK

<Info>
  **Supported on:** Android SDK `1.0.33+`
</Info>

This page provides a comprehensive reference for all public methods, properties, and types in the AppDNA Android SDK.

## Core Methods

Methods available directly on the `AppDNA` object.

| Method        | Signature                                                                                       | Description                                                                                                                 |
| ------------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `configure`   | `configure(context: Context, apiKey: String, environment: Environment, options: AppDNAOptions)` | Initialize the SDK. Call once in `Application.onCreate()`.                                                                  |
| `identify`    | `identify(userId: String, traits: Map<String, Any>?)`                                           | Associate events with a user ID and optional traits.                                                                        |
| `reset`       | `reset()`                                                                                       | Clear user identity, experiment exposures, in-session message/survey state, and stop entitlement observers. Call on logout. |
| `track`       | `track(event: String, properties: Map<String, Any>?)`                                           | Track a named event with optional properties.                                                                               |
| `flush`       | `flush()`                                                                                       | Force an immediate flush of all queued events.                                                                              |
| `onReady`     | `onReady(callback: () -> Unit)`                                                                 | Register a callback for when the SDK is fully initialized.                                                                  |
| `shutdown`    | `shutdown()`                                                                                    | Gracefully shut down the SDK and release resources.                                                                         |
| `setLogLevel` | `setLogLevel(level: String)`                                                                    | Change log verbosity at runtime. Accepts `"none"`, `"error"`, `"warning"`, `"info"`, `"debug"`.                             |
| `setLogLevel` | `setLogLevel(level: LogLevel)`                                                                  | Same as above, but takes the typed `LogLevel` enum.                                                                         |
| `setConsent`  | `setConsent(analytics: Boolean)`                                                                | Enable or disable analytics data collection.                                                                                |

## Session Data Methods

| Method             | Signature                                         | Description                                                                                                          |
| ------------------ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `setSessionData`   | `setSessionData(key: String, value: Any)`         | Store a key-value pair in the session data store.                                                                    |
| `getSessionData`   | `getSessionData(key: String): Any?`               | Retrieve a session data value by key.                                                                                |
| `clearSessionData` | `clearSessionData()`                              | Clear all app-defined session data.                                                                                  |
| `getLocationData`  | `getLocationData(fieldId: String): LocationData?` | Get structured location data from an onboarding location field. Returns city, state, country, coordinates, timezone. |

## Config Methods

| Method               | Signature                        | Returns   | Description                                         |
| -------------------- | -------------------------------- | --------- | --------------------------------------------------- |
| `getRemoteConfig`    | `getRemoteConfig(key: String)`   | `Any?`    | Retrieve a remote configuration value by key.       |
| `forceRefreshConfig` | `forceRefreshConfig()`           | `Unit`    | Force an immediate refresh of remote configuration. |
| `isFeatureEnabled`   | `isFeatureEnabled(flag: String)` | `Boolean` | Check whether a feature flag is enabled.            |

## Experiment Methods

| Method                 | Signature                                                | Returns   | Description                                            |
| ---------------------- | -------------------------------------------------------- | --------- | ------------------------------------------------------ |
| `getExperimentVariant` | `getExperimentVariant(experimentId: String)`             | `String?` | Get the assigned variant for an experiment.            |
| `isInVariant`          | `isInVariant(experimentId: String, variantId: String)`   | `Boolean` | Check if the user is in a specific experiment variant. |
| `getExperimentConfig`  | `getExperimentConfig(experimentId: String, key: String)` | `Any?`    | Get a configuration value for a specific experiment.   |

## Push Methods

| Method               | Signature                                          | Description                                        |
| -------------------- | -------------------------------------------------- | -------------------------------------------------- |
| `setPushToken`       | `setPushToken(token: String)`                      | Register the FCM push token.                       |
| `onNewPushToken`     | `onNewPushToken(token: String)`                    | Alternative method to register the FCM push token. |
| `setPushPermission`  | `setPushPermission(granted: Boolean)`              | Report push notification permission status.        |
| `trackPushDelivered` | `trackPushDelivered(pushId: String)`               | Track that a push notification was delivered.      |
| `trackPushTapped`    | `trackPushTapped(pushId: String, action: String?)` | Track that a push notification was tapped.         |

<Note>
  There is no `registerForPush()` helper on Android. Push permission (`POST_NOTIFICATIONS`) is a runtime permission on Android 13+ and is requested through `AppDNA.push.requestPermission(activity)`. See the [Push](/sdks/android/push) guide for the full setup.
</Note>

## Presentation Methods

| Method                      | Signature                                                                                                                      | Returns   | Description                                                                                                                                                  |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `presentOnboarding`         | `presentOnboarding(activity: Activity, flowId: String?, listener: AppDNAOnboardingDelegate?)`                                  | `Boolean` | Present an onboarding flow. Returns whether it was presented.                                                                                                |
| `presentPaywall`            | `presentPaywall(activity: Activity, id: String, context: PaywallContext?, listener: AppDNAPaywallDelegate?)`                   | `Boolean` | Present a paywall by ID. Returns whether a paywall was actually shown.                                                                                       |
| `presentPaywallByPlacement` | `presentPaywallByPlacement(activity: Activity, placement: String, context: PaywallContext?, listener: AppDNAPaywallDelegate?)` | `Boolean` | Top-level method on `AppDNA` (not `AppDNA.paywall`). Present whichever paywall the audience rules for `placement` resolve to. Returns whether one was shown. |

## Web Entitlements

| Member                    | Type                                    | Description                                      |
| ------------------------- | --------------------------------------- | ------------------------------------------------ |
| `webEntitlement`          | `WebEntitlement?` (property)            | The current web entitlement, if any.             |
| `onWebEntitlementChanged` | `(callback: (WebEntitlement?) -> Unit)` | Register a listener for web entitlement changes. |

## Deep Links

| Method                  | Signature                                                      | Description                                                             |
| ----------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `checkDeferredDeepLink` | `checkDeferredDeepLink(callback: (DeferredDeepLink?) -> Unit)` | Check for a deferred deep link and invoke the callback with the result. |

***

## Module Namespaces

The SDK exposes the following module namespaces for direct access:

| Namespace              | Type                  | Description                         |
| ---------------------- | --------------------- | ----------------------------------- |
| `AppDNA.push`          | `PushModule`          | Push notification management        |
| `AppDNA.billing`       | `BillingModule`       | Billing and subscription management |
| `AppDNA.onboarding`    | `OnboardingModule`    | Onboarding flow presentation        |
| `AppDNA.paywall`       | `PaywallModule`       | Paywall presentation                |
| `AppDNA.remoteConfig`  | `RemoteConfigModule`  | Remote configuration access         |
| `AppDNA.features`      | `FeaturesModule`      | Feature flag access                 |
| `AppDNA.experiments`   | `ExperimentsModule`   | Experiment variant access           |
| `AppDNA.inAppMessages` | `InAppMessagesModule` | In-app message management           |
| `AppDNA.surveys`       | `SurveysModule`       | Survey management                   |
| `AppDNA.deepLinks`     | `DeepLinksModule`     | Deep link handling                  |

Server-driven screens are accessed via top-level methods on `AppDNA` (`showScreen`, `showFlow`, `dismissScreen`, etc.) and the `AppDNA.screenDelegate` property — there is no `AppDNA.screens` module namespace.

***

## Delegate Interfaces

### AppDNAPushDelegate

```kotlin theme={null}
interface AppDNAPushDelegate {
    fun onPushTokenRegistered(token: String)
    fun onPushReceived(notification: PushPayload, inForeground: Boolean)
    fun onPushTapped(notification: PushPayload, actionId: String?)
}
```

### AppDNABillingDelegate

```kotlin theme={null}
interface AppDNABillingDelegate {
    fun onPurchaseCompleted(productId: String, transaction: TransactionInfo) {}
    fun onPurchaseFailed(productId: String, error: Throwable) {}
    fun onEntitlementsChanged(entitlements: List<Entitlement>) {}
    fun onRestoreCompleted(restoredProducts: List<String>) {}
    fun onBillingUnavailable() {}
}
```

### AppDNAOnboardingDelegate

```kotlin theme={null}
interface AppDNAOnboardingDelegate {
    fun onOnboardingStarted(flowId: String)
    fun onOnboardingStepChanged(flowId: String, stepId: String, stepIndex: Int, totalSteps: Int)
    fun onOnboardingCompleted(flowId: String, responses: Map<String, Any>)
    fun onOnboardingDismissed(flowId: String, atStep: Int)

    // Async hooks (optional)
    suspend fun onBeforeStepAdvance(flowId: String, fromStepId: String, stepIndex: Int, stepType: String, responses: Map<String, Any>, stepData: Map<String, Any>?): StepAdvanceResult
    suspend fun onBeforeStepRender(flowId: String, stepId: String, stepIndex: Int, stepType: String, responses: Map<String, Any>): StepConfigOverride?
}
```

### AppDNAPaywallDelegate

```kotlin theme={null}
interface AppDNAPaywallDelegate {
    fun onPaywallPresented(paywallId: String)
    fun onPaywallAction(paywallId: String, action: PaywallAction)
    fun onPaywallPurchaseStarted(paywallId: String, productId: String)
    fun onPaywallPurchaseCompleted(paywallId: String, productId: String, transaction: TransactionInfo)
    fun onPaywallPurchaseFailed(paywallId: String, error: Throwable)
    fun onPaywallDismissed(paywallId: String)
    fun onPromoCodeSubmit(paywallId: String, code: String, completion: (Boolean) -> Unit)
    fun onPostPurchaseDeepLink(paywallId: String, url: String)
    fun onPostPurchaseNextStep(paywallId: String)
    fun onPaywallRestoreStarted(paywallId: String)
    fun onPaywallRestoreCompleted(paywallId: String, productIds: List<String>)
    fun onPaywallRestoreFailed(paywallId: String, error: Throwable)
}
```

### AppDNAInAppMessageDelegate

```kotlin theme={null}
interface AppDNAInAppMessageDelegate {
    fun onMessageShown(messageId: String, trigger: String)
    fun onMessageAction(messageId: String, action: String, data: Map<String, Any>?)
    fun onMessageDismissed(messageId: String)
    fun shouldShowMessage(messageId: String): Boolean
}
```

### AppDNASurveyDelegate

```kotlin theme={null}
interface AppDNASurveyDelegate {
    fun onSurveyPresented(surveyId: String)
    fun onSurveyCompleted(surveyId: String, responses: List<SurveyResponse>)
    fun onSurveyDismissed(surveyId: String)
}
```

### AppDNADeepLinkDelegate

```kotlin theme={null}
interface AppDNADeepLinkDelegate {
    fun onDeepLinkReceived(url: String, params: Map<String, String>)
}
```

***

## Types

### AppDNAOptions

```kotlin theme={null}
data class AppDNAOptions(
    val flushInterval: Long = 30L,
    val batchSize: Int = 20,
    val configTTL: Long = 3600L,
    val logLevel: LogLevel = LogLevel.WARNING,
    val notificationIcon: Int = 0,
    val framework: String = "native",
    val frameworkVersion: String? = null,
    val billingProvider: BillingProvider = BillingProvider.StoreKit2,
    val requireConsent: Boolean = false,
    val vetoTimeout: Long = 5L,
)
```

### Environment

```kotlin theme={null}
enum class Environment(val baseUrl: String) {
    PRODUCTION("https://api.appdna.ai"),
    SANDBOX("https://api.appdna.ai") // same URL — sandbox routed via `adn_test_` key prefix
}
```

### LogLevel

```kotlin theme={null}
enum class LogLevel(val level: Int) {
    NONE(0),
    ERROR(1),
    WARNING(2),
    INFO(3),
    DEBUG(4)
}
```

### PaywallContext

```kotlin theme={null}
data class PaywallContext(
    val placement: String,
    val experiment: String? = null,
    val variant: String? = null,
    val customData: Map<String, Any>? = null // Merged into the `paywall_view` event's properties
)
```

### OnboardingContext

```kotlin theme={null}
data class OnboardingContext(
    val source: String? = null,
    val campaign: String? = null,
    val referrer: String? = null,
    val userProperties: Map<String, Any>? = null,
    val experimentOverrides: Map<String, String>? = null
)
```

### PushPayload

```kotlin theme={null}
data class PushPayload(
    val pushId: String,
    val title: String,
    val body: String,
    val imageUrl: String? = null,
    val data: Map<String, Any>? = null,
    val action: PushAction? = null,          // The notification's single primary action
    val actions: List<PushActionButton> = emptyList() // Every registered action button, in tray order
)
```

### PushAction

```kotlin theme={null}
data class PushAction(
    val type: String,
    val value: String
)
```

### PushActionButton

```kotlin theme={null}
data class PushActionButton(
    val id: String,
    val label: String,
    val type: String,
    val value: String? = null,
    val icon: String? = null
)
```

### TransactionInfo

```kotlin theme={null}
data class TransactionInfo(
    val transactionId: String,
    val productId: String,
    val purchaseDate: String,
    val environment: String
)
```

### Entitlement

```kotlin theme={null}
data class Entitlement(
    val productId: String,
    val store: String,
    val status: String,
    val expiresAt: String?,
    val isTrial: Boolean,
    val offerType: String?
)
```

### ProductInfo

```kotlin theme={null}
data class ProductInfo(
    val id: String,
    val name: String,
    val description: String,
    val formattedPrice: String,
    val priceMicros: Long,
    val currencyCode: String,
    val offerToken: String?
)
```

### PurchaseResult

```kotlin theme={null}
sealed class PurchaseResult {
    data class Purchased(val entitlement: Entitlement) : PurchaseResult()
    object Cancelled : PurchaseResult()
    object Pending : PurchaseResult()
    object Unknown : PurchaseResult()
    data class Failed(val error: String) : PurchaseResult()
}
```

### PaywallAction

```kotlin theme={null}
enum class PaywallAction(val value: String) {
    CTA_TAPPED("cta_tapped"),
    FEATURE_SELECTED("feature_selected"),
    PLAN_CHANGED("plan_changed"),
    LINK_TAPPED("link_tapped"),
    CUSTOM("custom")
}
```

### DismissReason

```kotlin theme={null}
enum class DismissReason(val value: String) {
    PURCHASED("purchased"),
    DISMISSED("dismissed"),
    TAPPED_OUTSIDE("tappedOutside"),
    PROGRAMMATIC("programmatic"),
    RESTORE_SUCCESS("restore_success")
}
```

### WebEntitlement

```kotlin theme={null}
data class WebEntitlement(
    val isActive: Boolean,
    val planName: String?,
    val priceId: String?,
    val interval: String?,
    val status: String,
    val currentPeriodEnd: Long?, // Unix seconds
    val trialEnd: Long?,         // Unix seconds
)
```

### DeferredDeepLink

```kotlin theme={null}
data class DeferredDeepLink(
    val screen: String,
    val params: Map<String, String>,
    val visitorId: String,
)
```

### StepAdvanceResult

```kotlin theme={null}
sealed class StepAdvanceResult {
    object Proceed : StepAdvanceResult()
    data class ProceedWithData(val data: Map<String, Any>) : StepAdvanceResult()
    data class Block(val message: String) : StepAdvanceResult()
    data class Stay(val message: String? = null) : StepAdvanceResult()
    data class SkipTo(val stepId: String, val data: Map<String, Any>? = null) : StepAdvanceResult()
}
```

### StepConfigOverride

```kotlin theme={null}
data class StepConfigOverride(
    val fieldDefaults: Map<String, Any>? = null,
    val title: String? = null,
    val subtitle: String? = null,
    val ctaText: String? = null,
    val layoutOverrides: Map<String, Any>? = null
)
```

### FormFieldType

```kotlin theme={null}
enum class FormFieldType(val value: String) {
    TEXT("text"), TEXTAREA("textarea"), NUMBER("number"),
    EMAIL("email"), PHONE("phone"),
    PASSWORD("password"),
    URL("url"),
    DATE("date"), TIME("time"), DATETIME("datetime"),
    SELECT("select"), SLIDER("slider"), TOGGLE("toggle"),
    STEPPER("stepper"), SEGMENTED("segmented"),
    LOCATION("location"),
    RATING("rating"),
    RANGE_SLIDER("range_slider"),
    IMAGE_PICKER("image_picker"),
    COLOR("color"),
    MULTILINE_CHIPS("multiline_chips"),
    SIGNATURE("signature")
}
```

### LocationData

```kotlin theme={null}
data class LocationData(
    val formatted_address: String = "",
    val city: String = "",
    val state: String = "",
    val state_code: String = "",
    val country: String = "",
    val country_code: String = "",
    val latitude: Double = 0.0,
    val longitude: Double = 0.0,
    val timezone: String = "UTC",
    val timezone_offset: Int = 0,
    val postal_code: String? = null,
    val raw_query: String = ""
)
```

***

## Server-Driven Screens

| Method                          | Signature                                                                  | Description                                                                                                     |
| ------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `showScreen`                    | `showScreen(screenId: String, callback: ((ScreenResult) -> Unit)? = null)` | Present a server-driven screen by ID.                                                                           |
| `showFlow`                      | `showFlow(flowId: String, callback: ((FlowResult) -> Unit)? = null)`       | Present a multi-screen flow by ID.                                                                              |
| `dismissScreen`                 | `dismissScreen()`                                                          | Dismiss the currently presented screen or flow.                                                                 |
| `enableNavigationInterception`  | `enableNavigationInterception(forScreens: List<String>?)`                  | Enable automatic screen injection between navigations. Pass null for all screens.                               |
| `disableNavigationInterception` | `disableNavigationInterception()`                                          | Disable navigation interception.                                                                                |
| `previewScreen`                 | `previewScreen(json: String): Boolean`                                     | Preview a screen from raw JSON config (callable in all build configurations). Returns whether it was presented. |
| `screenDelegate`                | `var screenDelegate: AppDNAScreenDelegate?`                                | Set a delegate for screen lifecycle callbacks.                                                                  |
| `isConsentGranted`              | `isConsentGranted(): Boolean`                                              | Check if analytics consent has been granted.                                                                    |
| `getUserTraits`                 | `getUserTraits(): Map<String, Any>`                                        | Get the current user traits set via `identify()` (empty map if none set).                                       |

### AppDNAScreenDelegate

The delegate uses untyped maps (rather than the typed `ScreenResult` / `FlowResult` data classes) so the SDK can add fields without breaking host implementations:

```kotlin theme={null}
interface AppDNAScreenDelegate {
    fun onScreenPresented(screenId: String) {}
    fun onScreenDismissed(screenId: String, result: Map<String, Any?>) {}
    fun onFlowCompleted(flowId: String, result: Map<String, Any?>) {}
    fun onScreenAction(screenId: String, action: Map<String, Any?>): Boolean = true
}
```

Common result-map keys: `screen_id`, `dismissed`, `responses`, `last_action`, `duration_ms`, `error`. Flow keys: `flow_id`, `completed`, `last_screen_id`, `responses`, `screens_viewed` (`List<String>`), `duration_ms`, `error`.

### ScreenError

```kotlin theme={null}
enum class ScreenError {
    CONFIG_FETCH_FAILED,
    CONFIG_FETCH_TIMEOUT,
    SCREEN_NOT_FOUND,
    CONFIG_PARSE_ERROR,
    CONFIG_INVALID,
    NESTING_DEPTH_EXCEEDED
}
```

### ScreenResult

Delivered to the `showScreen` top-level callback (not the delegate):

```kotlin theme={null}
data class ScreenResult(
    val screenId: String,
    val dismissed: Boolean = false,
    val responses: Map<String, Any> = emptyMap(),
    val lastAction: String? = null,
    val durationMs: Int = 0,
    val error: ScreenError? = null,
)
```

### FlowResult

Delivered to the `showFlow` top-level callback (not the delegate):

```kotlin theme={null}
data class FlowResult(
    val flowId: String,
    val completed: Boolean = false,
    val lastScreenId: String = "",
    val responses: Map<String, Any> = emptyMap(),
    val screensViewed: List<String> = emptyList(),
    val durationMs: Int = 0,
    val error: ScreenError? = null,
)
```

***

## Properties

| Property                      | Type                     | Description                                                                                                                             |
| ----------------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `AppDNA.sdkVersion`           | `String`                 | The current SDK version string (e.g., `"1.0.43"`).                                                                                      |
| `AppDNA.currentBundleVersion` | `Int`                    | The current config bundle version number.                                                                                               |
| `AppDNA.configUpdated`        | `SharedFlow<Unit>`       | Coroutine flow that emits when remote config is updated. Collect with `lifecycleScope.launch { AppDNA.configUpdated.collect { ... } }`. |
| `AppDNA.pushDelegate`         | `AppDNAPushDelegate?`    | Top-level proxy for the push delegate (mirror of `AppDNA.push.setDelegate(...)`).                                                       |
| `AppDNA.billingDelegate`      | `AppDNABillingDelegate?` | Top-level proxy for the billing delegate.                                                                                               |
| `AppDNA.screenDelegate`       | `AppDNAScreenDelegate?`  | Delegate for server-driven screen lifecycle.                                                                                            |
