> ## 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 Remote Config

> Dynamically configurable values delivered from the AppDNA Console

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

Remote config lets you ship app behavior changes without releasing a new app version. Define key-value pairs in the Console, target them by audience or experiment, and read them from the SDK at runtime.

## How It Works

1. You define remote config keys in the Console.
2. The SDK fetches the bundle (Firestore + REST fallback) when the app starts and listens for live updates.
3. Your app reads values via `AppDNA.remoteConfig.get(key)` and the SDK serves the latest cached value.
4. When values change server-side, an `onChanged` callback fires so your UI can react.

<Info>
  Remote config values are cached locally and survive offline use. The cache uses a configurable TTL (default 1 hour) — see [Offline Support](/sdks/android/offline) for cache behavior.
</Info>

## Get a Value

The Android SDK exposes a single typed-as-`Any?` getter — cast to the concrete type you stored:

```kotlin theme={null}
val welcomeMessage = AppDNA.remoteConfig.get("welcome_message") as? String
val tutorialEnabled = AppDNA.remoteConfig.get("tutorial_enabled") as? Boolean
val maxItems = (AppDNA.remoteConfig.get("max_items") as? Number)?.toInt()
val pricing = AppDNA.remoteConfig.get("pricing_tiers") as? Map<String, Any>
```

Return type is `Any?`. The SDK preserves the value shape the Console stored (string, number, boolean, list, map). Use `as?` casts to coerce to the expected type and default with `?:` when the key is missing.

The top-level convenience method `AppDNA.getRemoteConfig(key)` is equivalent to `AppDNA.remoteConfig.get(key)`.

## Get All Values

Retrieve the entire config map:

```kotlin theme={null}
val all = AppDNA.remoteConfig.getAll()
for ((key, value) in all) {
    Log.d("Config", "$key = $value")
}
```

Returns `Map<String, Any>` (empty map if config has not loaded yet).

## Force Refresh

Force the SDK to fetch the latest configuration from the server, bypassing the TTL cache:

```kotlin theme={null}
AppDNA.remoteConfig.refresh()
```

This is useful during development to test new config values without waiting for the TTL. The convenience method `AppDNA.forceRefreshConfig()` is equivalent.

<Warning>
  Refreshing too frequently in production may impact performance and consume bandwidth. Rely on the default TTL for normal operation.
</Warning>

## Listen for Changes

Register a callback that fires whenever remote config values change (live Firestore update or TTL refresh):

```kotlin theme={null}
AppDNA.remoteConfig.onChanged { configs ->
    Log.d("Config", "${configs.size} values updated")
    // configs is the full Map<String, Any> snapshot
    val newMessage = configs["welcome_message"] as? String
    refreshUiWith(newMessage)
}
```

The callback receives the full config snapshot — not just changed keys. Re-read whatever you care about and update your UI accordingly.

## When Config Refreshes

The SDK refreshes remote config automatically:

* **On app launch** — if the cached config has expired (default TTL: 1 hour)
* **On return from background** — same TTL check
* **Live Firestore updates** — when the Console publishes new values, the SDK applies them immediately via the active real-time listener

You rarely need to trigger a refresh manually. If a fetch fails (no connectivity, timeout), the SDK continues using the cached values until the next successful fetch.

<Info>
  The config TTL is configurable via `AppDNAOptions(configTTL = 1800L)` (in seconds). The default is 3600 seconds (1 hour).
</Info>

## Module Access

```kotlin theme={null}
val remoteConfig = AppDNA.remoteConfig
```

### Module Methods

| Method      | Signature                                         | Description                                        |
| ----------- | ------------------------------------------------- | -------------------------------------------------- |
| `get`       | `get(key: String): Any?`                          | Get a remote config value by key                   |
| `getAll`    | `getAll(): Map<String, Any>`                      | Get a snapshot of all remote config values         |
| `refresh`   | `refresh()`                                       | Force a fresh fetch from the server (bypasses TTL) |
| `onChanged` | `onChanged(callback: (Map<String, Any>) -> Unit)` | Register a callback for live config updates        |

## Targeting and Variants

Remote config values can be targeted by audience attributes (country, app version, user trait) or scoped to experiment variants. The SDK automatically resolves the correct value for the current user based on the active config bundle. No code changes are required — variant resolution is fully server-side.

## Full Example

```kotlin theme={null}
import ai.appdna.sdk.AppDNA
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class HomeActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        configureUi()

        // React to live config updates
        AppDNA.remoteConfig.onChanged {
            runOnUiThread { configureUi() }
        }
    }

    private fun configureUi() {
        val title = AppDNA.remoteConfig.get("home_title") as? String ?: "Welcome"
        val showBanner = AppDNA.remoteConfig.get("show_promo_banner") as? Boolean ?: false
        val bannerText = AppDNA.remoteConfig.get("promo_banner_text") as? String ?: ""

        titleView.text = title
        if (showBanner) {
            promoBanner.text = bannerText
            promoBanner.visibility = View.VISIBLE
        } else {
            promoBanner.visibility = View.GONE
        }
    }
}
```

## Configuration in Console

Manage remote config in the AppDNA Console:

1. Navigate to **Settings → Remote Config**.
2. Add a new key with a default value.
3. Optionally add variants targeted by audience or experiment.
4. Publish the config to push it to the SDK.

<Note>
  Remote config values are cached locally. To test new values immediately, call `AppDNA.remoteConfig.refresh()` or wait for the TTL to expire.
</Note>

## Next Steps

* Combine remote config with [Experiments](/sdks/android/experiments) for A/B testing
* Use [Feature Flags](/sdks/android/feature-flags) for typed boolean rollouts
* Configure [Offline Support](/sdks/android/offline) for cache TTL and fallback behavior
