-
Notifications
You must be signed in to change notification settings - Fork 0
English
An independently developed, native Android Java application for local area network (LAN) file transfers. Its goal is to provide compatibility with the device discovery and Upload API of LocalSend Protocol v2.2 on legacy devices (Android 2.3 through Android 6.0 / API 9 to API 23). The project does not reference, import, or build from any LocalSend source directories.
Current Version: 1.3 (versionCode 5).
Pre-compiled APK files are available for direct download and installation from the GitHub Releases page of this repository. Manual compilation is not required. Releases include v1 signatures ready for direct installation on legacy devices (Android 2.3 to 6.0).
If you wish to build the project manually, the following environment is required:
- JDK 17
- Gradle Wrapper 8.9
- Android Gradle Plugin 8.7.3
- Android SDK Platform 23 (Android 6.0 Marshmallow)
- Android SDK Build Tools 23.0.3 (or higher)
Build and verification command:
./gradlew testDebugUnitTest lintDebug assembleDebug
Compiled APK output path:
app/build/outputs/apk/debug/app-debug.apk
The project configures minSdkVersion 9, compileSdkVersion 23, and targetSdkVersion 23 (Android 6.0 Marshmallow). This ensures a lightweight and unified build environment fully aligned with the storage permissions and service semantics of the classic Android era. This project is not intended for publication on Google Play.
- UDP multicast device discovery, announcements, and response handling.
- HTTP/HTTPS LocalSend v2 (v2.2) registration endpoints.
- Support for Chunked Transfer Encoding.
- Single and multi-file selection, sending, and receiving.
- Accept / Decline prompt before receiving.
- File-level token, session ID, origin IP, and certificate fingerprint validation.
- Streaming uploads and disk saving without loading complete files into memory.
- Overall progress tracking, error notifications, and cancellation support from either side.
- Automatic renaming with
(1),(2)suffixes to prevent overwrites. - Compatibility with filenames containing Chinese characters, spaces, and special symbols.
- Foreground service for receiving; Activity recreation does not interrupt ongoing transfers.
- User interface localized in Simplified Chinese.
app/src/main/java/com/blithe/legacysend/
├── LegacySendApp.java App-level state, background tasks, and UI events
├── ReceiveService.java Foreground keep-alive receiving service
├── discovery/ UDP multicast discovery
├── model/ Data models for devices and files
├── protocol/ LocalSend JSON protocol formats (v2.2)
├── security/ Self-signed identity, BKS KeyStore, mTLS, certificate pinning, SimpleX509Generator
├── server/ HTTP/HTTPS endpoints (register, prepare, upload, cancel)
├── storage/ Storage handling with SAF, legacy file system, and renaming logic
├── transfer/ HTTPS/HTTP sending client, progress control, and cancellation
├── ui/ Native Android Views user interface
└── util/ Stream copying and transfer speed utilities
The source code is 100% Java—no dependencies on Kotlin, Jetpack Compose, Flutter, Dart, or React Native. Uses Groovy DSL for Gradle.
- minSdk 9 (Android 2.3) to Android 6.0 (API 23) Coverage: Specifically adapted for legacy hardware and firmware environments.
-
Certificate Generation on API 9–17: Custom
SimpleX509Generatorimplementation to resolve the absence ofAndroidKeyStoreand overcome strict ASN.1/DER parsing in OpenSSL / Conscrypt on Android 2.3–4.2. -
BKS KeyStore Format: Uses
BouncyCastle(BKS) on API 9–17 for storing private keys and certificates, preventingPKCS12serialization crashes on Android 2.3. -
ASN.1 / DER Structure Fixes: Wraps
AttributeTypeAndValueinSEQUENCEwithin the certificate hierarchy and explicitly changes the string type ofcommonName(2.5.4.3) toPrintableString(0x13), resolving the OpenSSLASN.1 encoding routines:OPENSSL_internal:WRONG_TAGexception. -
Y2K38 Overflow Mitigation: Self-signed certificates on API 9–17 use
SHA1withRSAsignatures with a validity limited to 10 years to prevent 32-bit integer timestamp overflows. -
Legacy File Access & SAF: API 19–23 uses
ACTION_OPEN_DOCUMENTwith SAF, while API 9–18 uses an internal file explorer to directly read external storage. -
TLS Reception Compatibility on Android 4.4.2 (API 19–20): The TLS 1.2 server on Kindle Android 4.4.2 only supports CBC ciphers, which are incompatible with the Rust TLS client in LocalSend 1.17.0. On API 19–20, receiving uses the official protocol
protocol: "http"mode. API 9–18 and API 21–23 maintain HTTPS for receiving and all outgoing transfers. -
Storage Paths: Save location is unified to the public
Download/LegacySendfolder across all supported versions (API 9–23). -
MulticastLock & Multithreading: Multicast listening is secured after acquiring
MulticastLock; all network and file I/O operations execute on background threads. - Stream Processing: Transfers use a 32 KiB buffer for chunked streaming, validating consistency between actual received bytes and metadata sizes.
- Notification System: Foreground Service uses traditional system notifications across API 9 to 23.
Zero third-party runtime dependencies. Uses only the Android SDK, Java Standard Library, and org.json (included in the operating system).
Test Dependencies:
- JUnit 4.13.2: Host JVM test execution only (not packaged into the APK).
-
org.json:json:20240303: Mock implementation for host JVM unit testing (not packaged into the APK).
- 12 host unit tests: protocol serialization, multi-file metadata, special/Chinese characters, accept/decline/cancel/timeout, renaming, SHA-256 hash calculation, and stream copying.
- Gradle build, Lint inspection, and debug APK packaging.
- Manifest verification confirming
minSdkVersion=9,compileSdkVersion=23, andtargetSdkVersion=23. - APK v1/v2 signature validation (v1 signature ready for installation on Android 2.3, 4.4.2, up to 6.0).
-
Physical Test on Android 2.3.6 (API 9): Self-signed certificate successfully generated and loaded (no
WRONG_TAGexception), HTTPS service started on port 53317, official LocalSend client discovered, single/multi-file chunked upload received and written to disk with matching SHA-256 hashes. - Physical Test on Kindle Android 4.4.2 (API 19): App startup, internal file selection, successful transfer to Android 11, and successful file reception from official LocalSend 1.17.0 with SHA-256 verification.
The DocumentsUI app on Kindle firmware retains records of deleted or moved downloads, throwing FileNotFoundException when attempting to open their content:// URIs. API 9–20 uses an internal file browser that directly lists existing and readable files from external storage; API 21–23 continues to use system SAF.
- Frequent Wi-Fi network switching on physical hardware, aggressive manufacturer battery optimization restrictions, and long-duration large file transfers on Android 5.0–6.0.
- LocalSend Reverse Download API (browser downloads); core Android-to-LocalSend Upload API does not depend on this.
- Secondary features such as PINs, history, clipboard sharing, themes, auto-updates, or user accounts.
- Fallback subnet IP scanning; currently relies on default multicast discovery and bi-directional
/registerconfirmation.
- Android Emulator 36 on Apple Silicon architecture does not support ARMv7 QEMU2 system images for API 9 or API 19.
Due to the lack of overlapping cipher suites between Android 4.4 system TLS and LocalSend 1.17.0, reception on API 19–20 operates in HTTP mode as allowed by the protocol specification. In this direction, files and metadata are not encrypted via TLS, though origin IP checks, random session IDs, and per-file tokens remain active. Use only on trusted local networks. Outgoing transfers from LegacySend and receiving on API 9–18 / API 21–23 enforce HTTPS encryption and certificate pinning.
For additional specification details and API endpoints, refer to [docs/protocol.md](https://www.google.com/search?q=docs/protocol.md).
Issues and Pull Requests are welcome. The primary goal of LegacySend is to provide a lightweight, stable, and interoperable transfer solution with LocalSend (v2.2) on legacy devices (Android 2.3 to Android 6.0 / API 9 to API 23). Preserving compatibility with older systems takes priority over adding new features.
- Maintain an independent implementation without copying or importing source code from LocalSend.
- Use strictly Java and native Android Views (avoid Kotlin, Jetpack Compose, Flutter, or Google Play Services).
- Keep the compatibility focus strictly within
minSdkVersion 9totargetSdkVersion 23. - Execute all network and file I/O operations on background threads using stream processing.
- Verify behavior on API 9, API 19, and Android 6.0 before submitting major changes.