Offline Chat is a simple Android messaging app that lets nearby phones discover and communicate with each other without using the internet or cellular data.
The app uses Google Nearby Connections with Bluetooth and Wi-Fi Direct to connect devices. Multiple devices can stay connected at the same time, which makes it possible to build a small local mesh of phones.
The main idea behind this project was pretty simple: what if you could send messages to nearby devices even when there is no internet?
- Send messages without an internet connection
- Discover nearby Android devices using Nearby Connections
- Keep multiple peer connections open at the same time
- Use a
P2P_CLUSTERnetwork so several devices can be connected together - Continue advertising and discovering devices in the background
- Rename your device so other users can identify it
- Start or stop discovery whenever needed
- Refresh the nearby-device list without disconnecting existing peers
- Send a message to all currently connected devices
- Receive notifications for messages when a chat isn't open
- Save chat history locally so messages aren't lost when the app is restarted
- Show timestamps for sent and received messages
The networking part of the app is built around Google's Nearby Connections API.
When discovery is enabled, a device does two things at the same time:
- Advertises itself so other devices can find it.
- Scans for other devices that are advertising.
When another device is found, the user can connect to it. Connection requests are automatically accepted, so there isn't a separate pairing screen.
After a connection is established, both devices continue advertising and discovering. This allows more devices to join the local network instead of stopping discovery as soon as the first connection is made.
Messages are sent using Nearby Connections' byte payloads and are stored locally for each peer.
Note: The current version creates the mesh connections, but it does not yet automatically relay a message through multiple devices. Multi-hop message forwarding is planned for a future version.
I intentionally kept the project fairly small and avoided adding libraries or architecture that weren't necessary for this version.
com.meshlink
├── ui/
│ └── Activities and RecyclerView adapters
│ ├── Splash
│ ├── Home
│ └── Chat
│
├── nearby/
│ └── NearbyController
│ └── Wrapper around Nearby Connections
│
├── model/
│ └── Device and Message models
│ └── Local/in-memory data stores
│
├── service/
│ └── MeshLinkService
│ └── Keeps discovery, advertising and
│ connections running in the background
│
└── utils/
├── PermissionsHelper
├── Prefs
└── TimeUtils
For this MVP, I didn't use Room, Hilt/Dagger, Compose, or a large MVVM setup. Most of the state is handled through simple Kotlin objects and local storage.
| Part | Technology |
|---|---|
| Language | Kotlin |
| UI | XML + ViewBinding |
| Design | Material 3 |
| Networking | Google Nearby Connections |
| Nearby library | play-services-nearby:19.3.0 |
| Storage | SharedPreferences + JSON |
| Concurrency | Kotlin Coroutines |
| Minimum SDK | 24 |
| Target SDK | 34 |
The permissions needed by Nearby Connections depend on the Android version.
| Android version | Main permissions |
|---|---|
| Android 11 and below | BLUETOOTH, BLUETOOTH_ADMIN, ACCESS_FINE_LOCATION |
| Android 12 | BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, BLUETOOTH_SCAN, ACCESS_FINE_LOCATION |
| Android 13+ | NEARBY_WIFI_DEVICES, BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, BLUETOOTH_SCAN, POST_NOTIFICATIONS |
| Android 14+ | FOREGROUND_SERVICE, FOREGROUND_SERVICE_CONNECTED_DEVICE |
The app handles these permissions at runtime through PermissionsHelper.kt.
You'll need:
- Android Studio (Koala or newer)
- Kotlin/Android SDK
- At least 2 physical Android phones
Physical devices are recommended because Nearby Connections depends on the Bluetooth and Wi-Fi hardware. Testing device-to-device discovery on emulators isn't reliable.
Clone the repository:
git clone https://github.com/<your-username>/offline-chat.git
cd offline-chatThen open the project in Android Studio and let Gradle finish syncing.
You can also install the debug build with:
./gradlew installDebugInstall the app on two or more physical devices.
- Open the app on each device.
- Grant the required permissions.
- Start discovery on each device.
- Wait for nearby devices to appear.
- Tap a device to connect.
- Once connected, open the device and start chatting.
- If multiple devices are connected, you can use Broadcast to All to send the same message to every connected peer.
This is still an MVP, so there are a few things that aren't implemented yet.
- Messages are currently limited to directly connected peers.
- There is no automatic multi-hop routing yet.
- There is no end-to-end encryption.
- Only text messages are supported.
- There are no delivery/read receipts.
- Group chats are not implemented yet.
Some ideas for future versions:
- Multi-hop message forwarding
- Proper mesh routing between devices
- Group chat rooms
- Image and file sharing
- Message delivery/read receipts
- End-to-end encryption
- Better handling of devices joining and leaving the network
I wanted to experiment with Android's peer-to-peer networking capabilities and see how far you can get with messaging when you completely remove the server and internet from the equation.
It was also a good way to learn more about Bluetooth/Wi-Fi based communication, background services, Android permissions, and handling connections between multiple devices.
This project is licensed under the MIT License. See LICENSE for more information.
Vedant Salve
B.Tech, Data Science & Engineering Dr. B.R. Ambedkar National Institute of Technology, Jalandhar