Offline Behavior

Durable on-disk event queue, WorkManager retry, network-aware flush

The Convert Android SDK is built so tracking events are never lost, even on a flaky or absent network. This is an Android-specific capability with no equivalent in the request-scoped JS or PHP SDKs — it relies on on-device durable storage, WorkManager, and connectivity callbacks.

What happens when the network is down

flowchart TD
    A[Decision / conversion call] --> B[Event enqueued in memory]
    B --> C{Flush succeeds?}
    C -->|Yes| D[Delivered to Convert]
    C -->|No / offline| E[Persisted to app-private file]
    E --> F[WorkManager job: convert-event-flush]
    F -->|Network available| G[Retry with exponential backoff]
    G --> D
    H[Connectivity regained] -->|NetworkObserver| F
    I[App returns to foreground] -->|restore| B
  1. Config fetch fails → the last successfully cached config is loaded from app-private storage (filesDir/convert-sdk/config.json). If no cache exists either, runExperience returns null until the next successful fetch.
  2. Tracking events generated while offline → persisted to a durable on-disk queue — a JSON file at filesDir/convert-sdk/events.json, written atomically (tmp file + rename). The queue survives app restarts and device reboots.
  3. Connectivity returns → a NetworkObserver (using ConnectivityManager.registerDefaultNetworkCallback) drains the persisted queue and triggers a flush.
  4. Backoff & retry → failed flushes reschedule via WorkManager with exponential backoff (10s base, doubling: 10s → 20s → 40s, capped). WorkManager survives app-kill and reboot, so an event enqueued today still ships after the user next launches the app.

Storage locations

WhatWhere
Offline event queuefilesDir/convert-sdk/events.json (app-private, mode 0700 parent dir)
Last-good config cachefilesDir/convert-sdk/config.json
Visitor id + sticky stateSharedPreferences file com.convert.sdk.visitor
Retry jobWorkManager unique work named convert-event-flush

All paths are inside the app's private sandbox and are removed on app uninstall.

Foreground / background handoff

The SDK observes the process lifecycle:

  • On background — it flushes the in-memory queue immediately, persists whatever survives the flush to events.json, and enqueues a convert-event-flush WorkManager job (with the REPLACE policy, so rapid background/foreground toggles collapse into one pending job). The job carries a NetworkType.CONNECTED constraint, so it stays idle until a network is available.
  • On foreground — it restores any events persisted on disk back onto the in-memory queue, then lets the normal batch timer ship them.

What you do not need to do

  • No manual flush — the SDK batches and flushes on its own.
  • No manual config refresh — the dataRefreshInterval timer handles re-fetching while the app is in the foreground.
  • No WorkManager registration — the SDK registers itself via AndroidX App Startup.

What is not persistent

  • Events for a visitor are stored in the app's private storage, so they are discarded on app uninstall or an explicit clear of app storage.

Permission note

The reconnect-triggered flush relies on ACCESS_NETWORK_STATE. Declare it for the best behavior:

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

If the permission is absent, registerDefaultNetworkCallback throws a SecurityException that the SDK catches and swallows — it degrades gracefully. Queued events still ship on the next scheduled batch; only the immediate "flush on reconnect" push is skipped. See Installation.

Inspecting the queue during development

# See the pending flush job.
adb shell dumpsys jobscheduler | grep convert-event-flush

You can also use Android Studio's App Inspection → Background Task Inspector to watch the convert-event-flush worker. See Troubleshooting.

Related pages