Config Field Drift
The most common silent failure in WebToApp: a feature works in preview but is quietly skipped in the exported APK because a config field name drifted between the export factory and the shell config class.
Why it happens
The shell reads its config with Gson, and Gson silently drops unknown or missing fields — no exception, no log. So if the JSON key written by the export factory does not exactly match the @SerializedName on the shell config field, the feature just… doesn't run, with no error.
The three things that must stay aligned:
- The payload keys in
ApkConfigJsonFactory.kt(the"key" to valuepairs). - The
@SerializedName("key")annotations inShellModeManager.kt's shell config classes. - The
ApkConfigfields they map from.
The gate
A CI gate checks this automatically:
./gradlew :app:checkConfigFieldDrift --no-configuration-cache
# or directly:
python3 scripts/check_config_field_drift.pyIt parses the payload keys out of ApkConfigJsonFactory.kt and the @SerializedName annotations out of ShellModeManager.kt, then reports any mismatch (subject to an allowlist in scripts/config_field_drift_allowlist.json).
Run it whenever you change config fields. It is part of the Android CI check job.
Diagnosis checklist
When a feature "works in preview, broken after export," check in this order:
- Did the shell config JSON actually contain the field at runtime?
- Does the field name in
ApkConfigJSON match the@SerializedNamein shell config? RuncheckConfigFieldDrift. - Is the runtime use site shell-synced (not host-only)?
- For adblock specifically: confirm
adBlockEnabledmapping, host filter rebuild from cached subscriptions, and export rule compile without wiping host state. - Rebuild the template after sync changes (stale template is a frequent miss).
Adding a setting that affects the generated APK
Trace and update all of:
- Model (
WebApp/ nested config) and editor UI binding. - Export mapping (
ApkBuilder/ApkConfig/ApkConfigJsonFactory). - Shell config types (
ShellModeManager/ shell config data classes) if the runtime reads them. - Runtime use site in shell-synced code.
- Unit tests for export wiring when flags change.
Missing any step usually yields: editor shows the switch, export ignores it, or export embeds config the runtime never reads.
