LinkMesh connects nearby Android phones over Bluetooth Low Energy and relays messages through each other, for blackouts, festivals, hikes and emergencies.
The MVP covers spec steps 1โ5: discovery, messaging, mesh relay, storage, chat UI and SOS.
Finds nearby LinkMesh phones over BLE and connects to the strongest ones automatically.
Every phone is a node. Messages hop up to 5 devices to reach someone out of range.
Shows โ sent, โ relayed and โโ delivered, plus "via N devices" for each message.
If a chain breaks, messages wait and continue when a path comes back.
One tap repeats an alert with GPS coordinates to every phone in the mesh.
With Bluetooth on, phones keep receiving and relaying in the background, even after a reboot.
A soft glass chime for messages, and an SOS alarm that sounds even on silent.
Uses a low-power hardware scan in the background and limits connections to 5.
The same flooding rules the app uses, run in your browser. Pick a sender, then a recipient, and press Send. Double-click (or long-press) a phone to switch it off and watch the route change.
Two custom sounds, synthesized for LinkMesh at 48 kHz / 16-bit.
A two-note glass chime rising a fifth (D6 โ A6): short, warm and easy to recognize in a pocket.
"ยทยทยท โโโ ยทยทยท" in Morse with bright two-tone beeps. It plays on the alarm channel, so it is heard even on silent.
Every phone runs both BLE roles at once. As a peripheral it advertises the LinkMesh service and accepts frames. As a central it scans, connects and writes frames to peers. The routing layer only uses a transport interface, so WiFi Direct and LoRa can be added later.
hop_count < max_hops, relay it with hop_count + 1.{
"id": "uuid-v4",
"type": "text | ack | sos",
"sender_id": "node-uuid",
"sender_name": "Ayesha",
"receiver_id": "node-uuid or *",
"timestamp": 1759500000000,
"content": "text message",
"hop_count": 0,
"max_hops": 5
}
| Layer | Code | Tech |
|---|---|---|
| UI | lib/ui/ | Flutter ยท Riverpod |
| Mesh routing | lib/mesh/mesh_router.dart | Flooding + dedupe + store-and-forward |
| Link layer | lib/ble/ble_transport.dart | flutter_blue_plus (central) ยท ble_peripheral (GATT server) |
| Storage | lib/data/ | SQLite (sqflite) |
You need two or more real devices: Android 8+ phones, iPhones (iOS 15+), or a Mac. Android and iPhone talk to each other. Emulators and the iOS Simulator have no Bluetooth radio, so they can't connect.
Apple only lets signed apps onto an iPhone. Until LinkMesh is on TestFlight, you sign the test build yourself with your free Apple ID. It takes about 5 minutes and needs a Mac or Windows PC and a USB cable.
Apps signed with a free Apple ID stop opening after 7 days. Just repeat step 3 to refresh it. Messages and settings are kept. AltStore works too and can refresh automatically over Wi-Fi.
iPhone notes: keep LinkMesh open (or recently used) for the best results. iOS pauses background apps, so an iPhone in the background stays reachable through links made while it was open, but isn't discovered by new Android phones. SOS alarms can't override silent mode on iPhone.
Once set up, phones keep receiving with the app closed while Bluetooth is on. Want to build it yourself? See the README.