# Android Cast (POC) **Roadmap & alpha:** [docs/ROADMAP.md](docs/ROADMAP.md) · **Alpha QA & feature freeze:** [docs/ALPHA.md](docs/ALPHA.md) · USB-C/HDMI: [docs/USB_HDMI_CAST.md](docs/USB_HDMI_CAST.md) · Commercial (dev-gated): [docs/COMMERCIAL.md](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) 1. Install the same APK on two devices on the **same Wi‑Fi**. 2. **Receiver:** **Receive** → transport **UDP** → stream protection **None** → **Start listening** (notification *Listening* / *Ready*). 3. **Sender:** **Send** → **UDP** → protection **None** → discover receiver → PIN → approve screen capture. 4. Watch **notifications** on both devices for status. 5. Stop from either notification **Stop** action. Full sign-off checklist: [docs/ALPHA.md](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 `Surface` attaches (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): ```bash 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](docs/GIT_FLOW.md).