Blazing-fast peer-to-peer file sharing over Wi-Fi Direct. No internet. No cloud. No account. Scan a code, confirm it matches, and send.
Sharing Plus connects two Android devices directly over Wi-Fi Direct — no router, no internet, no account — and moves files at full Wi-Fi speed over a raw socket, with an optional forced-5GHz fast path. Pairing is confirmed with a short match code shown on both devices before a single byte moves. Every transfer is logged locally; nothing ever touches a server.
Built with Jetpack Compose and a fully dynamic Material You color system — 8 curated palettes, custom hex, or your wallpaper's own colors — so the screenshots below are just one of many looks the app can wear.
| Package | com.willyshare.willykez |
| Min SDK | 24 (Android 7.0) |
| Language | 100% Kotlin, Jetpack Compose |
| Storage | Room (local history only), SAF (custom receive folder) |
| Network | Wi-Fi Direct (WifiP2pManager), raw NIO sockets |
🔗 Connectivity
- Live Wi-Fi Direct peer discovery, with automatic re-scanning so it never silently goes stale
- QR pairing built around a pull model — the device with files ready shows a code; the receiving device scans it and pulls the cart
- Forced 5GHz "High-speed Mode" where the chipset supports it, with a clean auto-band fallback
- A 4-digit match code shown on both devices before any transfer begins — closes the "auto-trust whoever you land on" gap that QR/discovery flows otherwise have
- Self-correcting connection roles: whichever device actually ends up as Wi-Fi Direct's Group Owner vs. Client, the right side pushes and the right side pulls, automatically
📤 Sending
- Grouped file browser with thumbnails, category tabs, multi-select, and live search
- Cart is decoupled from connection — pick files first or connect first, in either order
- Files shared in from other apps land straight in the cart
- Parallel multi-stream sending with live per-file progress and a real-time speed graph
📥 Receiving
- Always-on background listener — no need to sit on the Receive screen
- Custom save folder via Storage Access Framework, or the app's own default directory
- Foreground service keeps receiving alive while backgrounded
🎨 Design
- Full Material You dynamic theming: 8 curated palettes, custom hex, or system wallpaper colors, each with light/dark/black variants and adjustable shading intensity
- A dot-grid mesh + radar-scan background and hairline-accented cards, generated fresh from whichever color you pick — not hardcoded to one look
- Bottom sheets for quick actions (QR display, QR scanning, theme picker) instead of full-page navigation where it doesn't need to be
🔒 Trust & privacy
- Every socket connection opens with an explicit intent byte — the wire protocol never guesses who's pushing and who's pulling
- Nothing is written to disk, and nothing is sent, until both devices' users confirm the same match code
- Transfer history is explicitly excluded from Android cloud backup — a "no cloud" app that actually stays off the cloud
- No analytics, no ads, no network calls beyond the direct peer-to-peer link
Appearance — palette style, tonal previews, shading intensity, all live
A small mode-byte protocol sits on top of raw TCP, plus a separate one-shot handshake connection for the match-code confirm:
1. HANDSHAKE (its own short-lived connection, always first)
dialer → [MODE_HANDSHAKE][device name][4-digit code][push/pull]
acceptor's user sees the code, taps Confirm/Decline
acceptor → [1 = confirmed | 0 = declined]
dialer's own user must ALSO confirm locally before this counts as a yes
2. TRANSFER (only opened if step 1 returned true)
MODE_PUSH: dialer writes [fileCount][name, size, bytes]... → acceptor reads & saves
MODE_PULL: dialer requests → acceptor (who has the cart) switches roles for this
connection and writes its files down the same socket instead
The always-on receive listener never has to guess who's connecting or why — the first byte always tells it. And because the handshake is its own connection, a parallel multi-stream send never triggers duplicate confirm prompts.
app/src/main/java/com/willyshare/willykez/
├── MainActivity.kt — Compose navigation host, global PIN confirm sheet, back-stack
├── net/ — Wi-Fi Direct, raw socket transfer protocol, QR payload codec
│ ├── WifiDirectManager.kt
│ ├── FileTransfer.kt — FileSenderClient / FileReceiveServer, the mode-byte protocol
│ └── QrPairing.kt
├── ui/
│ ├── PulseViewModel.kt — single source of truth: cart, connection state, transfer state
│ ├── theme/ — dynamic Material You color derivation, curated palettes
│ └── screens/ — one file per screen/sheet
├── data/ — Room database (local transfer history only)
├── service/ — foreground service keeping receive-listening alive
└── util/ — notifications, share-intent handling, battery/Wi-Fi helpers
Standard Android Studio / Gradle project. Wi-Fi Direct doesn't work in the emulator — two physical devices are needed to test any actual transfer.
./gradlew assembleDebugBuilt independently. No ads, no tracking, no cloud.






