Bitchat Android Networking Transports: BLE, Wi-Fi Aware, and Nostr Implementation

Bitchat Android supports three networking transports—Bluetooth Low Energy (BLE), Wi-Fi Aware, and Nostr—unified under a MeshTransport abstraction that automatically routes messages over the best available peer-to-peer link.

The permissionlesstech/bitchat-android repository implements a resilient, decentralized messaging stack designed for offline-first communication. Understanding these networking transports is essential for developers building mesh networks that function with or without internet infrastructure.

The Three Core Networking Transports

Bitchat Android encapsulates each physical transport behind a common interface, allowing the routing layer to switch between them transparently based on hardware availability and peer proximity.

Bluetooth Low Energy (BLE) Mesh

The BLE transport provides short-range peer-to-peer communication using Android’s native Bluetooth Low Energy APIs. Implemented in app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt, this transport discovers nearby devices via BLE advertisements, establishes GATT connections, and exchanges encrypted packets directly over the radio link.

When initialized, the service registers itself with the TransportBridgeService under the identifier "BLE", enabling the routing core to include it in mesh path calculations. This transport requires no access point and functions completely offline.

Wi-Fi Aware Mesh

The Wi-Fi Aware transport leverages Android’s Neighbor Awareness Networking (NAN) APIs to create peer-to-peer Wi-Fi connections without requiring a traditional access point. This implementation resides in app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshService.kt and registers under the identifier "WIFI" with the transport bridge.

Wi-Fi Aware offers higher throughput than BLE over medium distances, making it ideal for scenarios where peers are within Wi-Fi range but lack traditional network infrastructure. The service dynamically creates and tears down data paths as peers move in and out of range.

Nostr Internet Transport

Unlike the local mesh transports, the Nostr transport provides global reachability over the internet using the Nostr decentralized relay protocol. Implemented in app/src/main/java/com/bitchat/android/nostr/NostrTransport.kt, this transport runs on top of the Tor/Arti stack for out-of-band communication when devices lack physical proximity.

Accessed via NostrTransport.getInstance(), this singleton transport does not register with the TransportBridgeService because it operates outside the local mesh routing layer. It handles direct messaging to Nostr public keys (npub) when internet connectivity is available.

Unified Transport Architecture

All local networking transports implement the MeshTransport interface defined in app/src/main/java/com/bitchat/android/mesh/MeshTransport.kt. This contract standardizes how the application sends and receives raw packets, regardless of the underlying radio technology.

The TransportBridgeService (located in app/src/main/java/com/bitchat/android/service/TransportBridgeService.kt) acts as a central hub, forwarding packets between the active transports and the higher-level routing logic. Application code interacts with the network through MessageRouter (app/src/main/java/com/bitchat/android/services/MessageRouter.kt), which provides a unified API abstracting the specific transport implementation.

Transport Selection and Routing

The routing core (MeshCore.kt) determines which networking transport to use for each peer by consulting PeerCapabilities.kt. This capability exchange allows devices to advertise which transports they support, enabling the router to select the optimal path—preferring local mesh transports (BLE or Wi-Fi Aware) over internet fallback (Nostr) when peers are physically proximate.

The bridge forwards incoming packets from any transport to the routing layer, which then handles decryption, verification, and delivery to the UI.

Code Examples

Registering the BLE transport manually with the bridge:

val meshService = com.bitchat.android.service.MeshServiceHolder.getOrCreate(context)
meshService?.let {
    com.bitchat.android.service.TransportBridgeService.register("BLE", it)
}

Sending a message through the automatic router:

val peerId = "abcdef1234"
val payload = "Hello, mesh!"

com.bitchat.android.services.MessageRouter.sendMessage(
    peerId = peerId,
    data = payload.toByteArray(),
)

Transmitting via the Nostr transport:

val nostr = com.bitchat.android.nostr.NostrTransport.getInstance(context)
nostr.sendDirectMessage(
    recipientNpub = "npub1xyz...",
    plaintext = "Hi over the internet!",
)

Summary

  • BLE Mesh: Short-range, low-power transport using GATT connections; identifier "BLE" in BluetoothMeshService.kt.
  • Wi-Fi Aware: Medium-range, high-throughput peer-to-peer transport; identifier "WIFI" in WifiAwareMeshService.kt.
  • Nostr: Internet-based transport over Tor/Arti for global reachability; accessed via singleton in NostrTransport.kt.
  • Unified Routing: TransportBridgeService coordinates local transports while MessageRouter provides the high-level API.
  • Smart Selection: MeshCore.kt evaluates PeerCapabilities.kt to choose the optimal transport for each message.

Frequently Asked Questions

Does Bitchat Android require an internet connection to function?

No. The application functions entirely offline using the BLE and Wi-Fi Aware networking transports, which create direct peer-to-peer links without cellular or Wi-Fi infrastructure. Internet connectivity is only required when explicitly using the Nostr transport for relay-based messaging.

What is the difference between the BLE and Wi-Fi Aware transports in Bitchat?

BLE operates at shorter ranges with lower power consumption, making it ideal for dense, proximity-based mesh networks. Wi-Fi Aware provides higher bandwidth over longer distances but consumes more power. Both register with TransportBridgeService under identifiers "BLE" and "WIFI" respectively, allowing MessageRouter to fallback between them dynamically.

How does the Nostr transport integrate with the local mesh network?

The Nostr transport operates independently of the mesh routing layer. Because it relies on internet relays rather than direct peer connections, it does not implement MeshTransport or register with TransportBridgeService. Applications access it directly via NostrTransport.getInstance() for out-of-band messaging when local mesh connectivity is unavailable.

Which file handles automatic transport selection?

Automatic selection logic resides in MeshCore.kt, which evaluates peer capabilities from PeerCapabilities.kt to determine whether to route through "BLE", "WIFI", or fall back to Nostr for a given destination peer.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →