Validates APK module layout and tolerates missing JDK 17 for gradlew help on developer machines.
AetherForge Agent APK (Phase 1)
Install the APK on your own devices so the embedded fleet agent joins the command-deck fleet table over WebSocket/C2. CPU mining is off by default in the baked config.
Main project overview: README.md · test coverage: tests/README.md.
Build
Requirements:
- Go 1.26+
- JDK 17+ (Android Gradle Plugin 8.x; Java 8 on PATH is not sufficient)
- Android SDK (
ANDROID_HOMEorANDROID_SDK_ROOT) - Gradle wrapper in
agent-app/(included; downloads Gradle 8.2 on first run)
# Windows
$env:AETHERFORGE_SERVER_URL = "https://your-deck.example.com:8989"
$env:AETHERFORGE_WORKER_NAME = "pixel-tab-01"
$env:AETHERFORGE_FLEET_SECRET = "your-fleet-secret" # optional; do not commit
.\android\build-apk.ps1
# Linux/macOS
export AETHERFORGE_SERVER_URL="https://your-deck.example.com:8989"
export AETHERFORGE_WORKER_NAME="pixel-tab-01"
export AETHERFORGE_FLEET_SECRET="your-fleet-secret"
./android/build-apk.sh
Output:
android/agent-app/build/outputs/apk/debug/aetherforge-agent.apk
The build script:
- Renders
assets/config.jsonand a temporaryagent/config/builtin.go - Cross-compiles
GOOS=linux GOARCH=arm64 CGO_ENABLED=0fromagent/intoassets/agent - Runs
assembleDebug
Install (adb)
adb install -r android/agent-app/build/outputs/apk/debug/aetherforge-agent.apk
adb shell am start -n com.aetherforge.agent/.MainActivity
First launch — permissions
Open the app once. You will see:
Your fleet node — tap Allow on each prompt.
The app requests all runtime permissions in one batch:
POST_NOTIFICATIONS(API 33+) — required for the foreground service notificationNEARBY_WIFI_DEVICES/ location — fleet Wi‑Fi diagnostics where the OS requires it
Then it opens battery optimization settings (REQUEST_IGNORE_BATTERY_OPTIMIZATIONS). Android cannot auto-grant these; you must tap Allow / Don't optimize.
After permissions, a low-priority persistent notification (Fleet sync) keeps AgentService alive. BootReceiver restarts the service on BOOT_COMPLETED.
How it runs
AgentServiceextractsassets/agent(linux/arm64) tofilesDir/bin/agent-arm64, marks it executable, and spawns it with--run.- Environment sets
HOME/TMPDIRto the app private files directory. - The agent uses forge-baked
builtin.govalues (server URL, worker name, fleet secret). Mining defaults to idle withIdleThresholdPct: 0(no CPU mining unless re-forged or changed by policy). - Wrapper sets
AETHERFORGE_PLATFORM=androidbefore spawn — Crucible shows 🤖, Access Depth uses Wi-Fi/battery/foreground probes, shortened mining onion (foreground service → in-process CPU).
Limitations
- No root — cannot install as system app or disable OEM kill policies globally.
- Notification required — foreground service must show a notification on modern Android.
- Binary execution — spawning a
GOOS=linuxbinary viaProcessBuilderworks on many arm64 devices (static Go build) but some OEMs block exec from app sandboxes. If the agent never appears in the fleet table, checkadb logcat -s AetherForge AetherForge:agent. A nativeGOOS=androidJNI approach is Phase 2 if exec fails on your hardware. - Secrets — pass
AETHERFORGE_FLEET_SECRETat build time via environment; never commit fleet secrets.
Tests
go test ./android/forge/... -count=1
bash android/smoke-gradle.sh
go test ./android/forge/... -count=1
.\android\smoke-gradle.ps1
smoke-gradle.sh validates the Gradle project layout and runs ./gradlew help when the wrapper is present.