Add Android APK fleet nodes with Crucible UI integration and tests.
APK wrapper registers platform=android via AETHERFORGE_PLATFORM; fleet UI shows robot icons, Android Access Depth probes, and a shortened mining onion timeline.
This commit is contained in:
81
android/README.md
Normal file
81
android/README.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# 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.
|
||||
|
||||
## Build
|
||||
|
||||
Requirements:
|
||||
|
||||
- Go 1.26+
|
||||
- Android SDK (`ANDROID_HOME` or `ANDROID_SDK_ROOT`)
|
||||
- Gradle wrapper in `agent-app/` (generate once with `gradle wrapper` if missing)
|
||||
|
||||
```powershell
|
||||
# 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
|
||||
```
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
1. Renders `assets/config.json` and a temporary `agent/config/builtin.go`
|
||||
2. Cross-compiles `GOOS=linux GOARCH=arm64 CGO_ENABLED=0` from `agent/` into `assets/agent`
|
||||
3. Runs `assembleDebug`
|
||||
|
||||
## Install (adb)
|
||||
|
||||
```bash
|
||||
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 notification
|
||||
- `NEARBY_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
|
||||
|
||||
1. `AgentService` extracts `assets/agent` (linux/arm64) to `filesDir/bin/agent-arm64`, marks it executable, and spawns it with `--run`.
|
||||
2. Environment sets `HOME`/`TMPDIR` to the app private files directory.
|
||||
3. The agent uses forge-baked `builtin.go` values (server URL, worker name, fleet secret). Mining defaults to idle with `IdleThresholdPct: 0` (no CPU mining unless re-forged or changed by policy).
|
||||
|
||||
## 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=linux` binary via `ProcessBuilder` works on many arm64 devices (static Go build) but **some OEMs block exec from app sandboxes**. If the agent never appears in the fleet table, check `adb logcat -s AetherForge AetherForge:agent`. A native `GOOS=android` JNI approach is Phase 2 if exec fails on your hardware.
|
||||
- **Secrets** — pass `AETHERFORGE_FLEET_SECRET` at build time via environment; never commit fleet secrets.
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
go test ./android/forge/... -count=1
|
||||
bash android/smoke-gradle.sh
|
||||
```
|
||||
|
||||
`smoke-gradle.sh` validates the Gradle project layout and runs `./gradlew help` when the wrapper is present.
|
||||
Reference in New Issue
Block a user