Looking back, dated to the day of the last commit.
MediaSync: photos from your phone to a USB stick, no cloud
For half a year I built an Android app on the side that backs up photos and videos straight to a USB stick. About 26,000 lines of Kotlin, on my own.
Plug the stick in, the backup runs, pull the stick out, and next time it picks up exactly where it stopped. That’s MediaSync in one sentence.
The question behind it was simple: how do I get photos and videos from my phone onto a USB stick and back without them passing through any cloud? I worked on it from April 5 until today, next to university. It ended up at about 26,000 lines of Kotlin in 155 files. My biggest mobile project of my own, all solo, but heavily agent-assisted. Better to say that up front.
Here’s how a backup runs, and the demo on this page shows the same thing with sample files. You plug in the stick. Android reports the device, and the app talks to the stick directly through the USB host interface. For that I use the libaums library, which reads and writes the FAT file system itself, without Android having to mount the stick. Then comes the preview: the app compares what’s on the phone with what’s already on the stick and only takes new files. It recognises identical files by their hash, not by their name.
MediaSync
Gesicherte Ordner
Then the actual copying. Large videos don’t go over in one piece but in chunks. Every chunk gets its own SHA-256 checksum, and which chunks have arrived safely is stored in a small database on the phone. Pull the stick out in the middle of a video and nothing breaks. Next time you plug it in, it continues at the first missing chunk.
A lot of Android grew around that core. A foreground service with a notification, so the backup doesn’t stop when you leave the app. A reminder for the next backup. A Quick Settings tile, three home-screen widgets and a share target for sending single pictures straight to it. Plus restoring from the stick, a report after every run, photo compression and a date stamp.
What doesn’t exist yet: feedback from other users. The repository only lives on my machine so far. Publishing it on GitHub is decided; before that I’ll check that no keys are in it and write a README.
What I’m taking away: with files people care about, “resume instead of restart” isn’t an extra, it’s the core. Without a checksum per chunk I would never know for sure whether an interrupted video is really complete. And background work on Android is a subject of its own. Services, workers and notifications each come with their own rules.
Tools and skills: Kotlin, Jetpack Compose for the UI, Hilt for dependency injection, Room as the database, WorkManager for background jobs, the Android USB Host API with libaums, hashing, and an architecture that keeps backup, restore and USB access cleanly apart.