# Android → PC File Drop Minimal Kotlin Android app that picks files/images and uploads them to a folder on a PC over the local network. ## Architecture Two pieces: 1. **PC receiver** — tiny HTTP server that accepts multipart uploads and writes files into a chosen folder. 2. **Android app** — one screen, one button: pick files → POST them to the PC. No cloud, no accounts, no discovery protocol. You type (or QR-scan) the PC's LAN IP once and save it. ## PC Receiver **Language:** Go (single binary). Go for "double-click and forget." **Behavior:** - Listen on `0.0.0.0:8787`. - `POST /upload` accepts `multipart/form-data`, saves each part to `DROP_DIR` with its original filename. - Collision policy: append ` (1)`, ` (2)`, etc. - Optional shared-secret header (`X-Auth: `) so randos on the same Wi-Fi can't dump files on you. - `GET /` returns "ok" for a health check. - Log each received file: name, size, source IP. it is seen on the local panel so that user locally can download **Config:** - `DROP_DIR` — where files land (default `~/Drops`). - `AUTH_TOKEN` — shared secret (generated on first run, printed + saved to config). - `PORT` — default 8787. **Firewall:** open the port on the PC's LAN profile only. ## Android App **Stack:** Kotlin, Jetpack Compose, single Activity, minSdk 26. **Screens:** one. **UI:** - Text field: PC address (e.g. `192.168.1.42:8787`), persisted in `DataStore`. - Text field: auth token, persisted. - Big button: "Pick files". - Below: list of currently-selected files with progress bars during upload. - Snackbar for success/failure per file. **Flow:** 1. Tap button → `ActivityResultContracts.OpenMultipleDocuments()` (handles images, video, any file; no storage permission needed on modern Android). 2. For each returned `Uri`: stream it as a multipart part to `http://
/upload` with the auth header. 3. Show per-file progress; on 200, mark done; on error, show retry. **Networking:** OkHttp with a `MultipartBody`, streaming from `contentResolver.openInputStream(uri)` so big videos don't OOM. **Manifest:** - `INTERNET` permission. - `usesCleartextTraffic="true"` scoped to local IP ranges via `network_security_config.xml` (HTTP is fine on LAN; adding TLS is a stretch goal). **Share target (stretch):** register as a share target so you can hit "Share → Drop to PC" from the Photos app. ## Protocol ``` POST /upload HTTP/1.1 Host: 192.168.1.42:8787 X-Auth: Content-Type: multipart/form-data; boundary=... --boundary Content-Disposition: form-data; name="file"; filename="IMG_1234.jpg" Content-Type: image/jpeg --boundary-- ``` Response: `200 OK` with JSON `{"saved": "IMG_1234.jpg"}` or `4xx/5xx` with error text. ## Milestones 1. PC receiver in ~60 lines; test with `curl -F file=@foo.jpg http://localhost:8787/upload -H "X-Auth: ..."`. 2. Android app scaffold: Compose UI, DataStore for settings, file picker returning URIs. 3. Wire up OkHttp multipart upload from a URI stream. 4. Progress + error UI. 5. Package: PC receiver as a systemd user service (Linux) or Task Scheduler entry (Windows) so it autostarts. Android side sideload the APK. ## Stretch - QR code on PC receiver's `GET /` page encoding `address + token` so first-time setup is scan-once. - mDNS advertisement (`_filedrop._tcp.local`) so the app can discover the PC without typing IPs. - TLS with a self-signed cert pinned in the app. - Share-target intent filter. - Resume interrupted uploads (`Content-Range`). ## Non-goals - PC → Android direction (use MTP or a second app instance later). - Internet / NAT traversal. - Multiple PCs at once (one address at a time is fine).