Moe Hamade 4a34408db9
Enhancement/apk sharing (#632)
* feat: Add QR code generator for Wi-Fi and URLs

This commit introduces a `QrCodeGenerator` utility object to create QR code bitmaps for both Wi-Fi credentials and URLs.

Key features:
- **`generateWifiQr`**: Creates a QR code using the standard `WIFI:` format, allowing other devices to connect to a hotspot by scanning the code. It properly escapes special characters in the SSID and password.
- **`generateUrlQr`**: Generates a standard QR code for any given URL.
- **Implementation**: Uses the `zxing` library to encode the data and converts the resulting `BitMatrix` into an Android `Bitmap`.

* feat: Add manager for universal APK sharing

This commit introduces a comprehensive system for fetching, downloading, caching, and managing a "universal" APK of the app, intended for offline sharing with new users.

The core components are:
- `GitHubReleaseClient`: A new client to fetch the latest release information from the project's GitHub repository. It specifically looks for a universal APK asset in the release, parses its download URL, and attempts to extract its SHA256 checksum from the release notes.
- `UniversalApkManager`: Manages the entire lifecycle of the universal APK. It handles:
    - Checking for new versions by comparing the cached APK version against the latest GitHub release.
    - Downloading the APK with progress reporting.
    - Verifying the downloaded file against the SHA256 checksum, if available.
    - Caching the APK and its metadata (version, checksum, size) locally.
    - Cleaning up old APK versions to conserve space.

* feat: Add offline APK sharing via Wi-Fi hotspot

This commit introduces a comprehensive feature for sharing the BitChat application offline using a self-hosted Wi-Fi Direct hotspot. This enables mesh network expansion by allowing users to distribute the app without requiring an internet connection.

Key components:
- **`HotspotManager`**: A new class that manages the creation and lifecycle of a Wi-Fi P2P (Wi-Fi Direct) group. It handles generating secure credentials (SSID/password), acquiring WakeLocks, and monitoring connected peers. It supports custom credentials on Android 10+ and falls back to system-generated ones on older versions.
- **`ApkWebServer`**: A lightweight HTTP server based on `NanoHTTPD` that serves the APK file and a user-friendly HTML landing page to connected devices.
- **`ApkSharingUtils`**: A utility to detect whether the app is installed as a single or split APK, collect the necessary files, and copy them to a cache directory for sharing.
- **`ApkInstaller`**: A utility using the `PackageInstaller` API to handle the installation of single or split APKs received from another user.
- **`HotspotActivity`**: A new Compose-based UI that guides the user through starting the hotspot, displays connection details (Wi-Fi credentials, QR codes for Wi-Fi and the download URL), and shows the number of connected peers. It also handles the necessary runtime permissions (`NEARBY_WIFI_DEVICES` or `ACCESS_FINE_LOCATION`).
- **Configuration**:
    - Adds necessary Wi-Fi and P2P permissions to `AndroidManifest.xml`.
    - Defines a `FileProvider` path for APK sharing in `file_paths.xml`.
    - Adds numerous string resources for the new UI.

* feat: Add offline and online app sharing features

This commit introduces a comprehensive feature set for sharing the application, both offline via a Wi-Fi hotspot and online through standard Android sharing mechanisms.

Key additions:

- **Prepare for Sharing UI:**
    - Adds a "Prepare App for Sharing" option in the settings sheet.
    - This feature downloads a universal APK from a remote source, suitable for all Android devices.
    - The UI displays the status: not downloaded, downloading (with progress), ready, or if an update is available.
    - Users can download, update, or delete the cached universal APK.

- **Offline Sharing via Wi-Fi Hotspot:**
    - Adds a "Share via Wi-Fi Hotspot" option.
    - This launches a new `HotspotActivity` to share the prepared universal APK with nearby devices without an internet connection.
    - A dialog informs the user if the APK hasn't been prepared yet.

- **Online & Local Sharing:**
    - Adds an option to share via Bluetooth, email, etc., using the standard Android share sheet.
    - This method shares the *installed* version of the app, which may be a split APK.
    - An explanatory dialog is shown first, instructing the receiver on how to install split APKs if necessary.
    - Implements logic to correctly package and share single or multiple split APK files using `FileProvider`.

* feat: Add NanoHTTPD for hotspot APK sharing

This commit introduces the `nanohttpd` library, which will be used to implement an HTTP server for sharing the application's APK over a local hotspot.

The specific dependency added is `org.nanohttpd:nanohttpd:2.3.1`.

* refactor: Improve hotspot and APK sharing stability

This commit introduces several fixes and refinements to the hotspot sharing and APK handling features, improving stability, user experience, and robustness.

Key changes:

-   **Hotspot Flow:**
    -   Automatically starts the hotspot after the user grants the required Wi-Fi permission, removing the need for a second button press.
    -   Ensures all `HotspotManager` callbacks in `HotspotViewModel` are executed within `viewModelScope` to prevent threading issues and ensure safe UI updates.
    -   Fixes a potential `BroadcastReceiver` leak in `HotspotManager` by tracking its registration state, preventing crashes and resource leaks when stopping the hotspot.
    -   Changes the hotspot `WakeLock` to be non-expiring to prevent the CPU from sleeping while the hotspot is active.

-   **APK Handling & Installation:**
    -   Adds a pre-download disk space check in `UniversalApkManager` to prevent download failures on devices with insufficient storage.
    -   Improves the file move logic after download by falling back to a copy-and-delete strategy if a direct rename fails, making it more robust across different filesystems.
    -   Introduces `InstallResultReceiver` to provide clear Toast notifications to the user about the success or failure of an APK installation, including specific error reasons (e.g., "Not enough storage").

-   **Performance & UI:**
    -   Caches the generated HTML in `ApkWebServer` to improve performance by avoiding regeneration on every request.
    -   Throttles the APK download progress updates to prevent UI jankiness from too-frequent state changes.
    -   Moves hardcoded strings in the "Share App" UI to `strings.xml` for better localization and maintenance.

* feat: Refactor APK sharing to use universal APK

This commit refactors the "Share App" functionality to exclusively use the new universal APK system, removing the previous logic that shared the installed split APKs. This simplifies the sharing process and ensures a consistent, single-file sharing experience for all users.

Key changes:
- Deletes `ApkSharingUtils.kt`, which was responsible for detecting and copying split APKs from the device's installation directory.
- Updates `AboutSheet.kt` to use `UniversalApkManager` for all sharing actions (Hotspot and "Quick Share").
- Simplifies the sharing intent logic, as it now only needs to handle a single APK file (`ACTION_SEND`) instead of multiple files (`ACTION_SEND_MULTIPLE`).
- The UI for sharing options (Hotspot, Quick Share) is now dynamically hidden until the universal APK is prepared, preventing user confusion.
- Replaces hardcoded strings with string resources for better localization.

* refactor: Remove InstallResultReceiver

Deletes the `InstallResultReceiver` broadcast receiver.

This component was responsible for handling the results of an APK installation initiated via `PackageInstaller`, but it is no longer used in the current implementation.

* feat: Move APK download to resumable WorkManager pipeline

Replaces the ViewModel-scoped coroutine download with a WorkManager-backed
downloader so downloads survive app backgrounding and process death:

- New ApkDownloader interface with WorkManagerApkDownloader implementation
  and ApkDownloadWorker (CoroutineWorker); transient IO errors return
  Result.retry() and resume via HTTP Range requests from the partial file.
- UniversalApkManager gains resume support (Range header + persisted resume
  metadata) and verifies the downloaded APK is signed with the same
  certificate as the running app (no hardcoded fingerprint; debug-signed
  builds skip enforcement).
- APK downloads now go through the shared OkHttpProvider so they respect
  the app's Tor proxy configuration instead of leaking the direct IP.
- AboutSheet logic extracted into ApkDownloadViewModel (MVI: state/event/
  effect), removing ~240 lines of UI-embedded logic.
- Removes unused ApkInstaller (receivers install via the system installer).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Harden hotspot server and release metadata fetching

- ApkWebServer only serves the exact /bitchat.apk path instead of any
  *.apk-suffixed URI.
- GitHubReleaseClient uses the shared OkHttpProvider (respects Tor proxy)
  and drops the loose 'any lone 64-hex string in the release notes is the
  checksum' fallback, which was spoofable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Address review findings in HotspotManager

- Keep polling for group info while the group is still forming instead of
  silently stopping when the first requestGroupInfo() returns null, with a
  15s formation timeout (Codex P1).
- Release wake/wifi locks and unregister the broadcast receiver on terminal
  startup failures via failStartup(), so a failed attempt no longer leaks
  resources or blocks subsequent attempts (Codex P2).
- Use PARTIAL_WAKE_LOCK with a 30-minute timeout instead of the deprecated
  FULL_WAKE_LOCK held indefinitely.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: harden offline APK sharing

* fix: Handle fully-downloaded temp file before adding Range header

If the process died after download_temp.apk was fully written but before
verification/promotion, the next attempt sent "Range: bytes=<size>-",
GitHub answered 416, and the worker retried the same request forever,
leaving the user stuck on an unresumable download.

- Skip the network entirely when the temp file already holds the full
  asset and go straight to checksum/signature verification.
- Treat an HTTP 416 response as an invalid resume offset: discard the
  partial state so the retry restarts from scratch instead of looping.

Addresses the Codex review finding on UniversalApkManager.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Allow sharing when the GitHub release lags the installed version

Upstream bumps versionName in main before tagging the GitHub release, so
there is a recurring window where the installed app is newer than the
latest published universal APK. The hard version guard disabled the whole
sharing feature during that window (including for reviewers building this
branch at 1.7.5 while GitHub's latest is 1.7.4).

An older release is still a genuine, signed, checksum-verified universal
artifact, and Android already refuses downgrade installs on receivers, so:

- checkForUpdate now logs (instead of erroring) when the latest release is
  older than the installed app and proceeds normally.
- downloadUniversalApk no longer fails for an older-than-installed release.
- A cached artifact stays shareable regardless of the installed version.

The cached-artifact preference (never replace a newer cached APK with an
older one) and all signature/checksum verification are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat: Run APK download as foreground (dataSync) work

Long transfers — especially over Tor — can exceed WorkManager's
~10-minute background execution window, getting the worker stopped and
rescheduled repeatedly. Promote the download to foreground work with a
progress notification (cancel action included) so it can run to
completion.

- setForeground() with FOREGROUND_SERVICE_TYPE_DATA_SYNC; the manifest
  already holds the FOREGROUND_SERVICE_DATA_SYNC permission, and the
  WorkManager SystemForegroundService is merged with type dataSync.
- If Android 12+ rejects the promotion (app backgrounded), the worker
  logs and continues as regular background work, relying on Range-resume.
- Notification updates are throttled to 5% steps and degrade gracefully
  without POST_NOTIFICATIONS.

Addresses the Codex review finding on ApkDownloadWorker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Move temp APK into place instead of copying it

replaceFileSafely copied the source into a .new candidate before the
atomic move, doubling peak disk usage: with free space between 1.5x and
2x the APK size, the download completed and then promotion failed on the
copy, retrying against the same full temp file.

Source and target always live in the same cache directory, so a direct
ATOMIC_MOVE (rename) needs no extra space and keeps the same guarantee:
it either fully succeeds or leaves both files intact. The existing 1.5x
margin in checkDiskSpace is now genuinely sufficient.

Addresses the Codex review finding on UniversalApkManager.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Base the disk space check on remaining bytes when resuming

The check ran before resume state was read and always demanded 1.5x the
full APK size. Bytes already sitting in download_temp.apk have already
consumed storage, so on a low-storage device an interrupted download
could fail every resume with "Insufficient storage" even when only a
small tail was left to fetch.

Read the resume state first and check space for the remaining bytes
only. A fresh download still checks the full size, and a complete temp
file needs no extra space since promotion is a rename.

Addresses the Codex review finding on UniversalApkManager.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: cancel APK downloads promptly

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
2026-07-27 02:45:07 +02:00
2026-07-27 02:45:07 +02:00
2026-07-27 02:45:07 +02:00
2026-01-15 11:45:22 +07:00
2025-08-04 13:50:03 +02:00
2025-07-08 20:37:46 +02:00
2025-07-08 20:37:46 +02:00
2026-02-03 15:33:56 +01:00
2025-08-29 14:37:35 +02:00

Bitchat Android Logo

Warning

This software has not received external security review and may contain vulnerabilities and may not necessarily meet its stated security goals. Do not use it for sensitive use cases, and do not rely on its security until it has been reviewed. Work in progress.

bitchat for Android

A secure, decentralized, peer-to-peer messaging app that works over Bluetooth mesh networks. No internet required for mesh chats, no servers, no phone numbers - just pure encrypted communication. Bitchat also supports geohash channels, which use an internet connection to connect you with others in your geographic area.

This is the Android port of the original bitchat iOS app, maintaining 100% protocol compatibility for cross-platform communication.

Install bitchat

You can download the latest version of bitchat for Android from the GitHub Releases page.

Or you can:

Get it on Google Play

Instructions:

  1. Download the APK: On your Android device, navigate to the link above and download the latest .apk file. Open it.
  2. Allow Unknown Sources: On some devices, before you can install the APK, you may need to enable "Install from unknown sources" in your device's settings. This is typically found under Settings > Security or Settings > Apps & notifications > Special app access.
  3. Install: Open the downloaded .apk file to begin the installation.

License

This project is released into the public domain. See the LICENSE file for details.

Features

  • Cross-Platform Compatible: Full protocol compatibility with iOS bitchat
  • Decentralized Mesh Network: Automatic peer discovery and multi-hop message relay over Bluetooth LE
  • End-to-End Encryption: X25519 key exchange + AES-256-GCM for private messages
  • Channel-Based Chats: Topic-based group messaging with optional password protection
  • Store & Forward: Messages cached for offline peers and delivered when they reconnect
  • Privacy First: No accounts, no phone numbers, no persistent identifiers
  • IRC-Style Commands: Familiar /join, /msg, /who style interface
  • Message Retention: Optional channel-wide message saving controlled by channel owners
  • Emergency Wipe: Triple-tap logo to instantly clear all data
  • Modern Android UI: Jetpack Compose with Material Design 3
  • Dark/Light Themes: Terminal-inspired aesthetic matching iOS version
  • Battery Optimization: Adaptive scanning and power management

Android Setup

Prerequisites

  • Android Studio: Arctic Fox (2020.3.1) or newer
  • Android SDK: API level 26 (Android 8.0) or higher
  • Kotlin: 1.8.0 or newer
  • Gradle: 7.0 or newer

Build Instructions

  1. Clone the repository:

    git clone https://github.com/permissionlesstech/bitchat-android.git
    cd bitchat-android
    
  2. Open in Android Studio:

    # Open Android Studio and select "Open an Existing Project"
    # Navigate to the bitchat-android directory
    
  3. Build the project:

    ./gradlew build
    
  4. Install on device:

    ./gradlew installDebug
    

Development Build

For development builds with debugging enabled:

./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

Release Build

For production releases:

./gradlew assembleRelease

Android-Specific Requirements

Permissions

The app requires the following permissions (automatically requested):

  • Bluetooth: Core BLE functionality
  • Location: Required for BLE scanning on Android
  • Network: Expand your mesh through public internet relays
  • Notifications: Message alerts and background updates

Hardware Requirements

  • Bluetooth LE (BLE): Required for mesh networking
  • Android 8.0+: API level 26 minimum
  • RAM: 2GB recommended for optimal performance

Usage

Basic Commands

  • /j #channel - Join or create a channel
  • /m @name message - Send a private message
  • /w - List online users
  • /channels - Show all discovered channels
  • /block @name - Block a peer from messaging you
  • /block - List all blocked peers
  • /unblock @name - Unblock a peer
  • /clear - Clear chat messages
  • /pass [password] - Set/change channel password (owner only)
  • /transfer @name - Transfer channel ownership
  • /save - Toggle message retention for channel (owner only)

Getting Started

  1. Install the app on your Android device (requires Android 8.0+)
  2. Grant permissions for Bluetooth and location when prompted
  3. Launch bitchat - it will auto-start mesh networking
  4. Set your nickname or use the auto-generated one
  5. Connect automatically to nearby iOS and Android bitchat users
  6. Join a channel with /j #general or start chatting in public
  7. Messages relay through the mesh network to reach distant peers

Android UI Features

  • Jetpack Compose UI: Modern Material Design 3 interface
  • Dark/Light Themes: Terminal-inspired aesthetic matching iOS
  • Haptic Feedback: Vibrations for interactions and notifications
  • Adaptive Layout: Optimized for various Android screen sizes
  • Message Status: Real-time delivery and read receipts
  • RSSI Indicators: Signal strength colors for each peer

Channel Features

  • Password Protection: Channel owners can set passwords with /pass
  • Message Retention: Owners can enable mandatory message saving with /save
  • @ Mentions: Use @nickname to mention users (with autocomplete)
  • Ownership Transfer: Pass control to trusted users with /transfer

Security & Privacy

Encryption

  • Private Messages: X25519 key exchange + AES-256-GCM encryption
  • Channel Messages: Argon2id password derivation + AES-256-GCM
  • Digital Signatures: Ed25519 for message authenticity
  • Forward Secrecy: New key pairs generated each session

Privacy Features

  • No Registration: No accounts, emails, or phone numbers required
  • Ephemeral by Default: Messages exist only in device memory
  • Cover Traffic: Random delays and dummy messages prevent traffic analysis
  • Emergency Wipe: Triple-tap logo to instantly clear all data
  • Bundled Tor Support: Built-in Tor network integration for enhanced privacy when internet connectivity is available

Performance & Efficiency

Message Compression

  • LZ4 Compression: Automatic compression for messages >100 bytes
  • 30-70% bandwidth savings on typical text messages
  • Smart compression: Skips already-compressed data

Battery Optimization

  • Adaptive Power Modes: Automatically adjusts based on battery level
    • Performance mode: Full features when charging or >60% battery
    • Balanced mode: Default operation (30-60% battery)
    • Power saver: Reduced scanning when <30% battery
    • Ultra-low power: Emergency mode when <10% battery
  • Background efficiency: Automatic power saving when app backgrounded
  • Configurable scanning: Duty cycle adapts to battery state

Network Efficiency

  • Optimized Bloom filters: Faster duplicate detection with less memory
  • Message aggregation: Batches small messages to reduce transmissions
  • Adaptive connection limits: Adjusts peer connections based on power mode

Technical Architecture

Binary Protocol

bitchat uses an efficient binary protocol optimized for Bluetooth LE:

  • Compact packet format with 1-byte type field
  • TTL-based message routing (max 7 hops)
  • Automatic fragmentation for large messages
  • Message deduplication via unique IDs

Mesh Networking

  • Each device acts as both client and peripheral
  • Automatic peer discovery and connection management
  • Store-and-forward for offline message delivery
  • Adaptive duty cycling for battery optimization

Android-Specific Optimizations

  • Coroutine Architecture: Asynchronous operations for mesh networking
  • Kotlin Coroutines: Thread-safe concurrent mesh operations
  • EncryptedSharedPreferences: Secure storage for user settings
  • Lifecycle-Aware: Proper handling of Android app lifecycle
  • Battery Optimization: Foreground service and adaptive scanning

Android Technical Architecture

Core Components

  1. BitchatApplication.kt: Application-level initialization and dependency injection
  2. MainActivity.kt: Main activity handling permissions and UI hosting
  3. ChatViewModel.kt: MVVM pattern managing app state and business logic
  4. BluetoothMeshService.kt: Core BLE mesh networking (central + peripheral roles)
  5. EncryptionService.kt: Cryptographic operations using BouncyCastle
  6. BinaryProtocol.kt: Binary packet encoding/decoding matching iOS format
  7. ChatScreen.kt: Jetpack Compose UI with Material Design 3

Dependencies

  • Jetpack Compose: Modern declarative UI
  • BouncyCastle: Cryptographic operations (X25519, Ed25519, AES-GCM)
  • Nordic BLE Library: Reliable Bluetooth LE operations
  • Kotlin Coroutines: Asynchronous programming
  • LZ4: Message compression (when enabled)
  • EncryptedSharedPreferences: Secure local storage

Binary Protocol Compatibility

The Android implementation maintains 100% binary protocol compatibility with iOS:

  • Header Format: Identical 13-byte header structure
  • Packet Types: Same message types and routing logic
  • Encryption: Identical cryptographic algorithms and key exchange
  • UUIDs: Same Bluetooth service and characteristic identifiers
  • Fragmentation: Compatible message fragmentation for large content

Publishing to Google Play

Preparation

  1. Update version information:

    // In app/build.gradle.kts
    defaultConfig {
        versionCode = 2  // Increment for each release
        versionName = "1.1.0"  // User-visible version
    }
    
  2. Create a signed release build:

    ./gradlew assembleRelease
    
  3. Generate app bundle (recommended for Play Store):

    ./gradlew bundleRelease
    

Play Store Requirements

  • Target API: Latest Android API (currently 34)
  • Privacy Policy: Required for apps requesting sensitive permissions
  • App Permissions: Justify Bluetooth and location usage
  • Content Rating: Complete questionnaire for age-appropriate content

Distribution

  • Google Play Store: Main distribution channel
  • F-Droid: For open-source distribution
  • Direct APK: For testing and development

Cross-Platform Communication

This Android port enables seamless communication with the original iOS bitchat app:

  • iPhone ↔ Android: Full bidirectional messaging
  • Mixed Groups: iOS and Android users in same channels
  • Feature Parity: All commands and encryption work across platforms
  • Protocol Sync: Identical message format and routing behavior

iOS Version: For iPhone/iPad users, get the original bitchat at github.com/jackjackbits/bitchat

Contributing

Contributions are welcome! Key areas for enhancement:

  1. Performance: Battery optimization and connection reliability
  2. UI/UX: Additional Material Design 3 features
  3. Security: Enhanced cryptographic features
  4. Testing: Unit and integration test coverage
  5. Documentation: API documentation and development guides

Support & Issues

For iOS-specific issues, please refer to the original iOS bitchat repository.

Description
bluetooth mesh chat, IRC vibes
Readme
Languages
Kotlin 85.8%
Java 10.1%
Python 2.6%
Shell 1.1%
Rust 0.3%
Other 0.1%