oa-android/ is a thin Android shell around the embedded oa-chat web app. Product logic stays in the oa-chat/ submodule; Android owns packaging, app links, WebView hardening, file-handling gaps, downloads, and ticket-export save semantics.
Live oa-chat app: chat.openanonymity.ai
AGENTS.mddocs/HOW_IT_WORKS.mddocs/ARCHITECTURE.mddocs/AGENT_LESSONS.mddocs/NATIVE_BACKGROUND_STREAMING_PLAN.mdwhen working on background execution
oa-chat/: read-only git submodule for the canonical web appapp/: Android application modulebuildSrc/: shared Gradle-side constants for the generated asset pipelinedocs/: repo-local implementation and handoff notes
- JDK 17
- Android SDK Platform 36
- Android Build Tools / cmdline tools that match AGP 8.13.x
- Node.js and npm available on
PATH - Initialized
oa-chatsubmodule
git submodule update --init --recursive
cd oa-chat
npm install
cd ..If the nested oa-chat/ submodule has not been initialized yet but you are working inside the shared OA workspace, the Gradle build can also fall back to the sibling checkout at ../oa-chat.
./gradlew :app:testDebugUnitTest
./gradlew :app:assembleDebug
./gradlew :app:connectedDebugAndroidTestThe root prepareOaChatDist task runs npm install + npm run build inside oa-chat/ and copies dist/ into generated Android assets. :app:preBuild depends on it, so normal app builds bundle the web app automatically.
- Keep
oa-chat/untouched from this repo. - Serve bundled assets on
https://chat.openanonymity.ai/withWebViewAssetLoader. - Preserve OA web URLs unchanged when routing App Links into the local WebView.
- Keep native bridges narrow and generic.
For the detailed explanation of where the wrapper stays thin, where it no longer does, and
what is currently worse than plain oa-chat, read docs/HOW_IT_WORKS.md.
Android now keeps active model streams alive across Home/app switching by moving the
active OpenRouter HTTP/SSE transport into a native foreground service while keeping
request construction, SSE parsing, UI, and normal chat state in oa-chat.
Current contract:
- access issuance still happens in
oa-chatbefore the native stream starts - once a stream starts, Android owns the network call and buffers SSE lines until the page polls them again
- reopening the app from the launcher no longer force-reloads the WebView if there is no deep link, so the in-flight page state survives launcher re-entry
- this MVP currently uses native direct HTTPS for the active model stream rather than the browser-side proxy/libcurl path
Remaining redesign work is tracked in docs/NATIVE_BACKGROUND_STREAMING_PLAN.md.
- JVM unit tests cover routing, asset resolution, MIME/path handling, external-link policy, save-picker result protocol, and build-layout wiring.
- Instrumentation tests cover asset loading, storage persistence, file input, App Link routing, ticket-export save/cancel semantics, and background streaming across Home/launcher resume via a native mock stream.