Shell Sync & Template
Generated APKs run the shell runtime, whose Kotlin sources are synced from app/. Understanding this sync is essential: edit the wrong copy and your change either gets overwritten or silently diverges.
The rule
Shared runtime sources are authored in
app/. Editing only a file undershell/srcis usually wrong; it will be overwritten on sync or diverge from host.
What enters the shell
shell/build.gradle.kts defines a syncShellRuntimeSources task with an include/exclude list that selects the full runtime set from app/ (e.g. core/shell, core/webview, core/engine, core/extension, ui/shell). Shell-specific overrides live in shell/src/main/java-overrides/.
Building the template
./gradlew :shell:assembleRelease :app:syncShellTemplateApk --no-configuration-cacheThis produces the single canonical template at app/src/main/assets/template/webview_shell.apk.
| Concern | Path |
|---|---|
| What enters shell | shell/build.gradle.kts → syncShellRuntimeSources include/exclude |
| Shell template build | :shell:assembleRelease + :app:syncShellTemplateApk |
| Template output | app/src/main/assets/template/webview_shell.apk |
| Config → shell JSON | app/.../apkbuilder/ApkConfigJsonFactory.kt |
| Shell config types | app/.../core/shell/ShellModeManager.kt |
| Runtime WebView config | app/.../ui/shell/ShellWebViewConfig.kt |
The shell runtime entry
At runtime, a generated APK:
WebToAppApplicationstarts.ShellModeManager.isShellMode()checks forapp_config.jsonin assets.- If present,
getConfig()deserializes it (via Gson) intoShellConfig— possibly decrypting it first. ShellServerLauncherresolves and launches server-backed runtimes;ShellRuntimeServicesinitializes the runtime stack.
Constraints
- One shell template. Do not introduce a second template APK.
- Low
targetSdk(28). Required for fork+exec runtimes. Do not raise it casually. - Thin dependency set. Do not pull host-only deps into
shell/build.gradle.kts. - Fail-soft notifications. FGS / notification channel creation must use
SafeNotificationChannels; channel creation failures must not crash FGS startup. - Configuration-cache safety. Custom Gradle tasks (
syncCloneHostDex, etc.) must captureFile/Providervalues at configuration time — do not referenceProject/android.sdkDirectoryinside task closures.
After changing shell membership
If you change what enters the shell or how the template is packaged, rebuild the template you touched. A stale template is one of the most frequent causes of "works in preview, broken after export."
./gradlew :shell:assembleRelease :app:syncShellTemplateApk --no-configuration-cache