4.8 KiB
Native Android build
Architecture and issue ownership: ADR and parity matrix. This scaffold implements #89. It is an installable native Compose foundation; onboarding, secure storage and native runtime packaging are implemented by their milestone issues.
Reproducible setup
Use a stable workspace Rust toolchain satisfying Cargo.toml, a JDK 25 installation (Android Studio's JetBrains Runtime 25 is suitable), Android SDK Platform 37, build-tools 36.0.0 and NDK 30.0.16248370. The app emits JVM 17-compatible code and supports minSdk 26. Set JAVA_HOME and ANDROID_HOME/ANDROID_SDK_ROOT or create an ignored local.properties containing sdk.dir. Cargo must be in the IDE/build process PATH, or set CARGO to its absolute executable path. No machine paths are committed.
The committed Gradle 9.8.1 wrapper verifies the distribution SHA-256. Its JAR SHA-256 is 3b8a25775a69158b5ad2b1d17a80a88dc7b40a352a73eb27d06c612a7ce68e98, verified against the official Gradle version metadata. AGP 9.4.1 includes Kotlin support; the Kotlin JVM/Compose plugin pin upgrades its classpath consistently to 2.4.20. Do not additionally apply kotlin-android with built-in Kotlin enabled. The version catalog is the single source for Android dependency/SDK/NDK pins.
From this directory:
./gradlew :app:assembleDebug :app:assembleRelease :app:testDebugUnitTest :app:lintDebug ktlintCheck
./gradlew :app:connectedDebugAndroidTest
Repeat the first command to verify configuration-cache reuse. Dependency verification is strict by default; committed SHA-256 metadata covers resolved build/test artifacts. Locks pin resolvable module configurations. To update an approved version, edit the catalog, verify the upstream artifact/release/license, then explicitly regenerate checksums/locks, inspect the diff and run the gates:
./gradlew :app:assembleDebug :app:assembleRelease :app:testDebugUnitTest :app:lintDebug ktlintCheck --write-verification-metadata sha256 --write-locks
Boundaries and fixtures
The app composition root injects an Android-facing ShellRepository. Compose features consume that contract through a Hilt ViewModel and collect immutable StateFlow state with lifecycle awareness. Only core depends on rust-bridge; platform implements core OS contracts. Gradle rejects forbidden module edges and competing domain dependencies. The Rust android-build tool checks Kotlin source/import boundaries and subprocess paths before every Android build. These static checks accompany code review; they do not prove arbitrary Kotlin code cannot conceal a domain implementation.
Debug-only Loading/Empty/Ready/Locked/Error fixtures are generated from the storage-owned MobileShell::fixture by the Rust build tool. Debug controls select the fixture and native tabs; these controls and generated fake states are absent from release. Release displays the scaffold state and does not pretend to have opened/decrypted a repository. Future #92 replaces scaffold wiring with generated UniFFI calls; feature code continues to consume the facade.
Identity, signing and update
All app build types keep de.rfc1437.ironstorage; test IDs are derived by AGP. Version code 1 and name 1.0.1 are deterministic initial metadata. Debug signing uses the standard local debug key. Release has no configured signing key and produces an unsigned APK; #112 configures protected upload signing. Do not add signing secrets or store passwords to the repository. Native symbol level FULL and the selected three ABIs are declared for later Rust packaging; the scaffold ships no native secret runtime or development network endpoint.
The manifest has only the exported launcher activity. Backup/cloud/device-transfer exclusions and cleartext denial are explicit. Feature-specific services/permissions are added with their owning issues. Resources use values directories for future localization; vector/adaptive/monochrome icons and R8 consumer rules are present. The launcher uses an unchanged copy of the iPhone vault artwork from apple/Assets.xcassets/AppIcon.appiconset/AppIcon.png, inset for Android's adaptive mask. Its themed monochrome layer keeps the round vault, wheel and hinge motif. Keep the two platforms' launcher branding aligned when updating that artwork.
Install updates over the existing simulator app without uninstall or data reset:
adb -s DEVICE install -r app/build/outputs/apk/debug/app-debug.apk
Keep the same AVD and application ID. Never wipe its data/keychain or seed a test app-data package as an update. After closing an issue, clean its project build outputs and Cargo target; preserve the emulator and shared SDK/toolchain caches. AGP's leaveApksInstalledAfterRun option is enabled so instrumented checks do not uninstall the app after running. Keep it enabled for this persistent test device.