If you use an Android phone with a Mac, you know the pain. You want to send a photo from your phone to your desktop. AirDrop? Apple-only. Cables? Good luck finding one, and MTP is notoriously unreliable. Cloud upload? Wait for upload, wait for download, burn through storage. Email it to yourself? We've all done it. It's embarrassing that we still do.
This week, we built Flyng—a macOS menu bar app that makes your Mac appear in Android's native Quick Share. Tap to send on your phone, click to accept on your Mac, file lands in Downloads. The way it should have worked from day one.
What we built
Flyng implements Google's Quick Share protocol natively on macOS. When you share a file on Android and select Quick Share, your Mac appears as a target device alongside other Android phones and tablets. No app to install on your phone, no account to create, no cloud service in the middle.
The key features that make this work:
Native protocol implementation — We reverse-engineered the Quick Share protocol so your Mac speaks the same language as Android devices. Discovery happens in under 3 seconds.
End-to-end encryption — Every transfer uses UKEY2 key exchange with AES-256 encryption. A 4-digit PIN appears on both devices for visual verification. Files never leave your local network.
Menu bar simplicity — Lives in your menu bar, not your dock. Toggle visibility when you want to appear or hide from nearby devices. Accept or decline transfers with a single click.
Files transfer at whatever speed your network allows—we've tested at 50MB/s on gigabit ethernet. A 1GB video transfers in about 20 seconds, not the minutes you'd wait for a cloud upload and download.
How we built it
The tech stack is pure Apple: Swift 5.9, SwiftUI for the preferences panel, AppKit for the menu bar, Network.framework for TCP connections, and CryptoKit for all the encryption. No external dependencies for crypto means no supply chain concerns and native Apple Silicon performance.
The interesting challenge was the protocol itself. Quick Share isn't documented. We pieced together the implementation from open-source projects, protocol buffer definitions, and packet captures. The discovery mechanism uses mDNS with a specific service type (_FC9F5ED42C8A._tcp) and a carefully encoded service name with magic bytes. Get any byte wrong and Android simply won't see your Mac.
Day 3 was almost entirely cryptography—implementing UKEY2 key exchange with P-256 elliptic curve Diffie-Hellman, then deriving encryption keys with HKDF-SHA256. The 4-digit PIN verification comes from hashing the shared secret. Both devices independently calculate the same PIN, proving they've established the same secure channel without an attacker in the middle.
One pragmatic decision: we built this as a CLI-based menu bar app rather than a full GUI application. The trade-off is we can't use Apple's modern notification system (UNUserNotificationCenter), but NSAlert works perfectly for our needs. Simpler architecture, faster build, same user experience.
Honest reflections
What went well: the protocol research upfront paid dividends. Spending day 1 understanding the complete message flow meant less debugging later. Network.framework's async/await support made connection handling clean, and CryptoKit has everything needed for UKEY2—no wrestling with OpenSSL or third-party libraries.
What was harder than expected: TCP frame boundary handling caused sporadic connection drops that took hours to trace. TCP doesn't guarantee message boundaries, so we had to implement an accumulation buffer with length prefix parsing. The documentation we found also had incorrect field ordering for PayloadChunk messages—another few hours of byte-by-byte debugging.
What we'd do differently: start with comprehensive logging from day one. We added detailed protocol logging after hitting the frame boundary issue, which immediately made subsequent debugging faster. Should have been there from the start.
The final app is about 9,500 lines of Swift and TypeScript (for the licensing backend), packaged into a 2.4MB DMG. Memory usage sits at around 15MB and stays stable even during large transfers.
The 52 Products challenge
Flyng is week 9 of our year-long challenge to ship a product every week. Each build demonstrates the same approach we use for client MVP Sprints: focused scope, aggressive timelines, production-ready output.
This week required reverse-engineering an undocumented protocol, implementing cryptographic key exchange, handling network edge cases, building licensing infrastructure, and getting through Apple's notarisation process. Five days. One developer.
The constraint forces pragmatic decisions. Menu bar app instead of full GUI. NSAlert instead of custom notification UI. Stream files to disk instead of buffering in memory. Each choice trades theoretical perfection for actual shipping.
Try it
Flyng is live at flyng.app. Free tier gives you 10 transfers per month—enough to see if it fits your workflow. Pro licence removes the limit if you're moving files between Android and Mac regularly.
If you're building something that needs to ship in days not months, that's what we do for clients too. MVP Sprints deliver working, deployed products in 5 days. Same approach, your product.

