Supported on: Android SDK
1.0.33+Config Resolution Priority
The SDK resolves configuration using a three-tier priority system:The SDK uses a stale-while-revalidate pattern. Cached config is served immediately while a fresh copy is fetched from the remote source in the background.
Config TTL
The cached configuration has a time-to-live (TTL) that defaults to 3600 seconds (1 hour). You can customize this value inAppDNAOptions:
Config Update Notifications
Listen for config updates by collecting theAppDNA.configUpdated coroutine flow:
AppDNA.configUpdated is a SharedFlow<Unit> that emits whenever the SDK applies a new remote config bundle (initial load, TTL refresh, or live Firestore push). It mirrors iOS’s Notification.Name(AppDNA.configUpdated) and Flutter/RN bridge events.
Cache Keys
The SDK persists configuration data in SharedPreferences under the namespaceai.appdna.sdk. Per-module keys are isolated so partial failures (e.g., paywall config update mid-fetch) cannot leak state across modules:
Bundled Config
For first-launch scenarios or environments with no network access, include a static configuration file in your app assets:- In the AppDNA Console, navigate to SDK > Config Bundle.
- Download the
appdna-config.jsonfile. - Place the file at
src/main/assets/appdna-config.json.
Event Queue
Events tracked withAppDNA.track(...) are not sent immediately. They are queued locally and flushed in batches.
Queue Behavior
Events are flushed when either condition is met (whichever occurs first). You can also call
AppDNA.flush() to trigger an immediate flush.
Persistence
Events are persisted to disk immediately when tracked. This ensures that:- Events survive app crashes and force quits.
- Events survive app restarts and device reboots.
- Events are delivered on the next successful flush after connectivity is restored.
The event queue is stored in a local SQLite database under the SDK’s private namespace. Events remain queued until they are successfully delivered to the AppDNA backend or the user revokes analytics consent. Apps upgrading from older SDK versions automatically migrate legacy SharedPreferences-backed event queues on first launch.
Adaptive Batch Sizing
The SDK automatically adjusts batch size based on network conditions reported byConnectivityManager.NetworkCapabilities:
- Wi-Fi: 100 events per batch
- Cellular: 50 events per batch
- Metered cellular (roaming / data saver): 20 events per batch
Event Storage Limits
Events are stored locally with the following limits:- Maximum 10,000 events in queue
- Maximum 5MB disk usage
Networking
OkHttp Timeouts
The SDK uses OkHttp3 for all HTTP requests with the following timeout configuration:Retry Strategy
When a flush attempt fails, the SDK retries with exponential backoff:
After 3 failed attempts, the request is abandoned and events remain in the queue for the next flush cycle.
Error Handling
Circuit Breaker
After 5 consecutive upload failures, event uploads are paused until the next app session (a foreground event resets the failure count and resumes uploads). A single failure does not pause uploads. Every failed flush counts toward the consecutive-failure total — whether a 4xx batch was dropped or a 5xx/network error left the batch queued for retry — and only the 5th failure in a row trips the circuit breaker.Request Headers
All requests include the following headers:Consent and Offline Behavior
When analytics consent is set tofalse:
Consent state is persisted in SharedPreferences. If a user revokes consent and restarts the app, the SDK remembers the revoked state and continues to drop events until consent is explicitly granted again.
Secure Storage
The following data is stored using Android’sEncryptedSharedPreferences (Android Keystore-backed) for security:
EncryptedSharedPreferences uses AES-256-GCM via the Android Keystore, so these values are protected by hardware encryption on supported devices.
Device Identification
The SDK generates an anonymous identifier as a randomUUID on first launch and persists it in secure storage. It is not derived from Settings.Secure.ANDROID_ID or any device hardware identifier. The anonymous ID is preserved across AppDNA.reset() — reset() clears only the identified user ID and user traits, leaving the anonymous ID (and its event attribution) intact.
Coroutine Scopes
The SDK uses Kotlin coroutines with the following dispatcher assignments:All SDK operations are non-blocking. Network requests and persistence operations run on the IO dispatcher, while UI-related callbacks (billing flows, paywall/onboarding rendering) are dispatched on the Main thread.
Summary
Next Steps
- Review the full API Reference for all available methods
- Learn about Push Notifications for offline token handling
- See the Remote Config guide for caching strategies

