Android Cast (POC)
Roadmap & alpha: docs/ROADMAP.md · Alpha QA & feature freeze: docs/ALPHA.md · Production infra (agents: read first): docs/INFRA.md · USB-C/HDMI: docs/USB_HDMI_CAST.md · Commercial (dev-gated): docs/COMMERCIAL.md
Minimal LAN screen-casting proof of concept in Java. Captures screen + playback audio, encodes H.264 + AAC, streams over TCP or UDP to a receiver that decodes and plays back.
Features
- UDP broadcast discovery on the local network
- UDP (default) or TCP stream transport (selectable; must match on both devices)
- PIN auth (SHA-256 hash, default
1234) - Screen capture → H.264 (AVC) with quality presets and scaled capture resolution
- Playback audio capture (API 29+) → AAC-LC
- Camera capture modes (API 29+, rear/front) — best-effort
- Runtime notification permission (Android 13+)
Quick start (alpha)
- Install the same APK on two devices on the same Wi‑Fi.
- Receiver: Receive → transport UDP → stream protection None → Start listening (notification Listening / Ready).
- Sender: Send → UDP → protection None → discover receiver → PIN → approve screen capture.
- Watch notifications on both devices for status.
- Stop from either notification Stop action.
Full sign-off checklist: docs/ALPHA.md.
If video never appears
- Transport must match on both sides (e.g. both UDP).
- Stream protection None on both sides for alpha.
- Receiver must show Listening or Ready before you cast.
- Sender notification should reach Casting with resolution — if it shows Screen capture data missing, reinstall (Android 13+ intent fix).
- Open receiver playback once so the video
Surfaceattaches (or return after rotation). - On rotation-sensitive senders, try system rotation lock during cast.
Build
Use JDK 17 or 21 (Gradle does not run on JDK 25 yet):
export JAVA_HOME=/usr/lib/jvm/openjdk-bin-21
cd "/home/foxx/repos/My Projects/android cast"
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
Stream options (defaults)
| Option | Default / alpha note |
|---|---|
| Transport | UDP (CastConfig.DEFAULT_TRANSPORT) |
| Stream protection | None |
| Quality | Medium — 5 Mbps, 30 fps |
| Resolution | Adaptive (sender) |
| Multi-receiver | Off while CastConfig.ALPHA_FEATURE_FREEZE |
| Audio | On when API 29+ (AudioPlaybackCapture + AAC) |
| Quality | Video bitrate | FPS |
|---|---|---|
| Low | 1.5 Mbps | 24 |
| Medium | 5 Mbps | 30 |
| High | 10 Mbps | 30 |
Protocol
| Step | Description |
|---|---|
| Discovery | UDP 41234, JSON with magic, name, port, transport |
| Connect | TCP or UDP port 41235 (QUIC 41236 when enabled post-alpha) |
| Auth | HELLO → AUTH → AUTH_OK → CAST_SETTINGS |
| Stream | STREAM_CONFIG, VIDEO_FRAME, AUDIO_CONFIG, AUDIO_FRAME |
UDP frames use ACUD header and fragmentation for payloads > ~1.2 KB.
Bluetooth / BLE
Not viable for this video stream. Use Wi‑Fi for media; BLE could be added later only for discovery/pairing.
Persistent services (AIDL)
Casting runs in foreground services with tray notifications:
| Service | Role |
|---|---|
ScreenCastService |
Sender — capture, encode, stream |
ReceiverCastService |
Receiver — listen, decode, play |
Activities bind via AIDL for status and (on the receiver) attaching the video Surface. Leaving the app does not stop the receiver listener; the sender keeps casting until Stop in the notification.
Limitations
- No TLS encryption (LAN cleartext POC)
- UDP mode may glitch under load (try TCP)
- Audio captures playback routed through the system (not microphone)
- Single receiver per session during alpha freeze
- No live sender preview while casting (stability)
Development (git flow)
Green master plus integration branch next. See docs/GIT_FLOW.md.
PDF helpers
Generate the GraphVis decision memo PDF (from docs/GRAFANA_vs_others_graphvis_pivot.md source):
bash scripts/build-graphvis-pdf.sh
Output:
docs/GRAFANA_vs_others_graphvis_pivot.pdf