99 lines
No EOL
3.6 KiB
Markdown
99 lines
No EOL
3.6 KiB
Markdown
# 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: <token>`) 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://<address>/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: <token>
|
|
Content-Type: multipart/form-data; boundary=...
|
|
|
|
--boundary
|
|
Content-Disposition: form-data; name="file"; filename="IMG_1234.jpg"
|
|
Content-Type: image/jpeg
|
|
|
|
<bytes>
|
|
--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). |