5.2 KiB
Who Need Help for Android
This module is a native Android WebView shell for the Phoenix application. It keeps authentication cookies, LiveView WebSockets, MapLibre, and chat in the same trusted origin. Live location is sent by a user-started native foreground service with a persistent notification and Stop action, so it can continue while the Activity is minimized without requesting Android's background-location permission.
Verified build configuration
- Android Gradle Plugin 9.3.0
- Gradle 9.6.1
- Android SDK Command-line Tools 22.0
- Android CLI 1.0.15857036 (embedded in the locked Command-line Tools archive)
- compileSdk / targetSdk 37
- Build Tools 37.0.0
- Java source and bytecode level 17
- minSdk 24 (project baseline, not an Android SDK requirement)
The debug origin is not stored in the Dockerfile or Gradle project. Set
WNH_DEBUG_BASE_URL in the repository's ignored .env file. The supplied
local configuration uses loopback together with adb reverse; debug builds
allow cleartext traffic, while the WebView still restricts in-app navigation to
that one configured origin.
The same ignored file supplies WNH_TRACKING_MIN_TIME_MS and
WNH_TRACKING_HTTP_TIMEOUT_MS. The checked-in example preserves the original
local client freshness and timeout behavior; these values are not claimed as
measured production capacity settings.
Release builds do not have a default server. Supply the real HTTPS deployment:
./gradlew :app:assembleRelease \
-PWNH_BASE_URL=https://help.your-domain.example \
-PWNH_TRACKING_MIN_TIME_MS=5000 \
-PWNH_TRACKING_HTTP_TIMEOUT_MS=15000
The build rejects a missing, HTTP, credentialed, query-bearing, or fragment-bearing release URL.
Public staging build
The installable staging build type uses the explicit public HTTPS
WNH_BASE_URL, disables cleartext traffic, and has its own
org.whoneedhelp.mobile.staging application ID. Configure a missing local value
from the existing PHX_HOST, PHX_SCHEME, and PHX_URL_PORT, then build:
./scripts/ensure-local-public-origin.sh
./scripts/android-staging-build.sh
sha256sum android/dist-staging/who-need-help-staging.apk
This variant uses Android's generic debug signing key so it can be installed
for staging verification. It is not a production-signed artifact and must not
be published as a release. The manifest accepts same-origin HTTPS deep links,
but verified Android App Links additionally require the final signing
certificate fingerprint in the deployment's /.well-known/assetlinks.json.
Reproducible Docker build
From the repository root:
./scripts/android-build.sh
sha256sum android/dist/who-need-help-debug.apk
The Docker build runs JVM unit tests, Android lint, assembleDebug, and
assembleDebugAndroidTest before it exports the application APK and lint
report.
Automated device tests
Run the default API 37 suite or the complete API 30/34/37 matrix from the repository root:
./scripts/android-instrumentation-test.sh
./scripts/android-matrix-test.sh
The command requires /dev/kvm. It generates an ignored
.env.android-test once with a randomized http://127.0.0.1:PORT origin and
mode 0600; the application and its in-process fixture server both derive the
origin from that file. It then builds both APKs, boots a fresh selected emulator
container without external networking, injects emulator coordinates, and runs
AndroidJUnitRunner. WNH_ANDROID_TEST_API selects one supported API, while
WNH_ANDROID_TEST_API_MATRIX controls the matrix command.
The tests cover the missing-location-permission boundary, the WebView-triggered
Android permission dialog, same-origin deep-link routing across Activity
recreation, foreground location upload after Home and Activity destruction, the
persistent notification Stop action, a disconnected Stop request with visible
retry state, and externally forced process death for the non-sticky tracking
service. Results are stored by API under ignored
output/android-instrumentation/. On failure, logcat, service state, and
emulator logs are retained; the exact container and one-run image are removed
in either outcome.
Emulator verification
The optional emulator target contains the API 37.0 Google APIs x86_64 system
image. Manual verification against the local Compose application requires KVM
and host networking. Pass the same .env value as a build argument, then
expose the Compose proxy to Android with adb reverse:
set -a
. ./.env
set +a
docker build \
--build-arg "WNH_DEBUG_BASE_URL=$WNH_DEBUG_BASE_URL" \
--build-arg "WNH_TRACKING_MIN_TIME_MS=$WNH_TRACKING_MIN_TIME_MS" \
--build-arg "WNH_TRACKING_HTTP_TIMEOUT_MS=$WNH_TRACKING_HTTP_TIMEOUT_MS" \
--target emulator \
-t who-need-help-android:emulator \
android
docker run --rm --name who-need-help-android-emulator \
--device /dev/kvm \
--network host \
who-need-help-android:emulator
docker exec who-need-help-android-emulator adb reverse tcp:4010 tcp:4010
docker exec who-need-help-android-emulator adb install \
/opt/who-need-help/who-need-help-debug.apk
The application ID org.whoneedhelp.mobile is provisional until the publishing
identity and store listing are chosen. Changing it after publication creates a
different Android application.