lingochamp/FileDownloader
Multitask、MultiThread(MultiConnection)、Breakpoint-resume、High-concurrency、Simple to use、Single/NotSingle-process
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓6 active contributors
- ✓Apache-2.0 licensed
- ✓CI configured
Show all 6 evidence items →Show less
- ✓Tests present
- ⚠Stale — last commit 2y ago
- ⚠Concentrated ownership — top contributor handles 52% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/lingochamp/filedownloader)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/lingochamp/filedownloader on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: lingochamp/FileDownloader
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/lingochamp/FileDownloader shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 6 active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 2y ago
- ⚠ Concentrated ownership — top contributor handles 52% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live lingochamp/FileDownloader
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/lingochamp/FileDownloader.
What it runs against: a local clone of lingochamp/FileDownloader — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in lingochamp/FileDownloader | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 672 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of lingochamp/FileDownloader. If you don't
# have one yet, run these first:
#
# git clone https://github.com/lingochamp/FileDownloader.git
# cd FileDownloader
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of lingochamp/FileDownloader and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "lingochamp/FileDownloader(\\.git)?\\b" \\
&& ok "origin remote is lingochamp/FileDownloader" \\
|| miss "origin remote is not lingochamp/FileDownloader (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "library/src/main/java/com/liulishuo/filedownloader/FileDownloader.java" \\
&& ok "library/src/main/java/com/liulishuo/filedownloader/FileDownloader.java" \\
|| miss "missing critical file: library/src/main/java/com/liulishuo/filedownloader/FileDownloader.java"
test -f "library/src/main/java/com/liulishuo/filedownloader/services/FileDownloadService.java" \\
&& ok "library/src/main/java/com/liulishuo/filedownloader/services/FileDownloadService.java" \\
|| miss "missing critical file: library/src/main/java/com/liulishuo/filedownloader/services/FileDownloadService.java"
test -f "library/src/main/java/com/liulishuo/filedownloader/model/FileDownloadModel.java" \\
&& ok "library/src/main/java/com/liulishuo/filedownloader/model/FileDownloadModel.java" \\
|| miss "missing critical file: library/src/main/java/com/liulishuo/filedownloader/model/FileDownloadModel.java"
test -f "library/src/main/java/com/liulishuo/filedownloader/database" \\
&& ok "library/src/main/java/com/liulishuo/filedownloader/database" \\
|| miss "missing critical file: library/src/main/java/com/liulishuo/filedownloader/database"
test -f "library/src/main/java/com/liulishuo/filedownloader/connection" \\
&& ok "library/src/main/java/com/liulishuo/filedownloader/connection" \\
|| miss "missing critical file: library/src/main/java/com/liulishuo/filedownloader/connection"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 672 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~642d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/lingochamp/FileDownloader"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
FileDownloader is an Android engine for parallel multi-task, multi-threaded file downloads with built-in breakpoint-resume, connection pooling across multiple simultaneous connections, and high-concurrency support. It abstracts HTTP connectivity, file I/O, and breakpoint state persistence so apps can download multiple files efficiently without managing threads or recovery logic manually. Single-module structure: library/src/main/java/com/liulishuo/filedownloader/ contains the core download engine, service logic, and database layer; demo/src/ holds Android sample apps; checkstyle.xml and .idea/ config enforce code style. Customization via pluggable interfaces (FileDownloadConnection, FileDownloadOutputStream, FileDownloadDatabase, etc.) lets users swap HTTP client or storage backend.
👥Who it's for
Android developers building apps that need reliable bulk file downloads (e.g., media apps, installers, content managers) who want to avoid reinventing retry logic, thread pools, and resume-on-interrupt behavior. Contributors are primarily the LingoCamp/Jacksgong team maintaining the core library.
🌱Maturity & risk
Production-ready but in maintenance mode: the project is 695KB of Java code with a complete gradle build, CI via Travis, and published to Bintray, but the README explicitly redirects new features to the successor project FileDownloader2 (okdownload) because unit-test coverage is very low. Active maintenance for bug fixes only, not active feature development.
Single-maintainer risk is real—the project defers all new work to okdownload, meaning unfixed bugs may not get attention. Low test coverage (explicitly mentioned) makes refactoring unsafe. The library hasn't transitioned to AndroidX (gradle version 3.3.1 is dated), and there's no visible SemVer discipline in CHANGELOG, so breaking changes in minor versions are possible.
Active areas of work
No active development—this is in bug-fix-only mode. The README and CHANGELOG suggest that all new features are happening in the successor project okdownload (lingochamp/okdownload). Travis CI is configured but recent commit activity is not visible in the file list.
🚀Get running
git clone https://github.com/lingochamp/FileDownloader.git
cd FileDownloader
./gradlew build
./gradlew :demo:assembleDebug
Daily commands:
Build the demo APK via ./gradlew :demo:assembleDebug, then install on emulator/device. Alternatively, add implementation 'com.liulishuo.filedownloader:library:1.7.7' to your own Android app's build.gradle and call the FileDownloader API directly (initialize, start(), add listeners, manage tasks).
🗺️Map of the codebase
library/src/main/java/com/liulishuo/filedownloader/FileDownloader.java— Main public API entry point—all download operations start here; understand this firstlibrary/src/main/java/com/liulishuo/filedownloader/services/FileDownloadService.java— Core background service managing download tasks, threading, and lifecycle—the engine of the systemlibrary/src/main/java/com/liulishuo/filedownloader/model/FileDownloadModel.java— Data model representing a single download task with state, progress, and metadatalibrary/src/main/java/com/liulishuo/filedownloader/database— Persistence layer for download state and recovery—critical for breakpoint-resume functionalitylibrary/src/main/java/com/liulishuo/filedownloader/connection— HTTP connection pool and multi-connection download logic—handles the actual network I/Olibrary/src/main/java/com/liulishuo/filedownloader/task/FileDownloadTask.java— Individual download task executor—orchestrates connection, buffering, and state transitionslibrary/src/main/AndroidManifest.xml— Declares FileDownloadService and required permissions; required for service initialization
🛠️How to make changes
Add a New Download Task
- Create a BaseDownloadListener subclass in your code to handle download events (onPending, onProgress, onComplete, onError) (
library/src/main/java/com/liulishuo/filedownloader/listener/FileDownloadListener.java) - Call FileDownloader.getImpl().create(url) to get a task builder, set destination and listener, then call start() (
library/src/main/java/com/liulishuo/filedownloader/FileDownloader.java) - Optionally use FileDownloadQueueSet or TasksManager for managing multiple downloads together (
library/src/main/java/com/liulishuo/filedownloader/task/FileDownloadQueueSet.java)
Enable Breakpoint-Resume
- Database must be initialized; by default FileDownloadDatabase persists all task state (
library/src/main/java/com/liulishuo/filedownloader/database/FileDownloadDatabase.java) - Call FileDownloader.getImpl().create(url).setAutoRetryTimes(n) to enable automatic retry on connection failure (
library/src/main/java/com/liulishuo/filedownloader/FileDownloader.java) - On app restart, query FileDownloadMgr for previously started tasks and call resume() to continue from checkpoint (
library/src/main/java/com/liulishuo/filedownloader/database/FileDownloadMgr.java)
Configure Multi-Connection Parallel Download
- Set max concurrent downloads via FileDownloadInitializer or FileDownloadConfiguration (
library/src/main/java/com/liulishuo/filedownloader/FileDownloadInitializer.java) - FileDownloadUrlConnection will automatically use range requests if the server supports HTTP 206 (
library/src/main/java/com/liulishuo/filedownloader/connection/FileDownloadUrlConnection.java) - Each task may spawn multiple connection threads via ConnectionProxy; monitor via listener callbacks (
library/src/main/java/com/liulishuo/filedownloader/connection/ConnectionProxy.java)
Migrate to Single vs. Multi-Process Mode
- By default FileDownloader runs downloads in a background service; toggle via FileDownloadService configuration (
library/src/main/java/com/liulishuo/filedownloader/services/FileDownloadService.java) - For single-process: use FileDownloader.getImpl() in main app process and disable IPC messenger (
library/src/main/java/com/liulishuo/filedownloader/message/FileDownloadMessenger.java) - Update AndroidManifest.xml to remove or keep the service declaration depending on mode (
library/src/main/AndroidManifest.xml)
🔧Why these technologies
- Android Service (Background) — Keeps downloads alive even if the app is backgrounded; decouples download lifecycle from UI
- SQLite Database — Persists download state for breakpoint-resume and crash recovery without network round-trips
- ThreadPoolExecutor — Controls concurrency and prevents thread explosion when managing many parallel downloads
- URLConnection with HTTP Range Requests (RFC 7233) — Enables multi-connection parallel downloads and efficient resumption from known byte offsets
- IPC (Messenger/Binder) — Allows multi-process architecture where downloads run in a separate service process for stability
⚖️Trade-offs already made
-
Separate background service vs. in-process downloads
- Why: Isolating downloads in a service prevents app crashes from blocking downloads, but adds IPC overhead
- Consequence: Single-process mode is faster but riskier; multi-process mode is stable but incurs 5–10% overhead
-
SQLite persistence for every progress update
- Why: Immediate durability enables crash recovery, but frequent writes create I/O contention
- Consequence: undefined
🪤Traps & gotchas
API thread safety: Callbacks likely fire on background threads—callers must marshal updates to main thread manually (no dispatcher pattern built in). Database initialization: RemitDatabase requires Android Context and may block on first access; not initialized implicitly. ProGuard: demo includes proguard-rules.pro—production builds risk breaking reflection-based serialization without proper config. Multi-process caveat: README mentions 'Single/NotSingle-process' support, but the mechanism (ContentProvider vs IPC) is not obvious from file structure—verify before using in multi-process apps. Gradle 3.3.1 is old: no AndroidX, no Java 8 desugaring by default; may fail on modern Android SDK levels without manual updates.
🏗️Architecture
💡Concepts to learn
- Breakpoint Resume / Partial Content (HTTP 206) — Core feature of FileDownloader—downloading only missing bytes via Range headers; understand how state is persisted in RemitDatabase and how RandomAccessFile seeks to the right offset
- Multi-Connection / Chunked Download — FileDownloader divides a file into multiple ranges and downloads them in parallel threads; ConnectionCountAdapter controls how many threads—essential for understanding performance knobs
- Thread Pool & Task Queue — FileDownloader manages concurrent downloads via a bounded thread pool; understanding queue behavior and backpressure is critical to avoid resource exhaustion or memory leaks
- Android Handler / Looper & Message Passing — FileDownloader likely uses Handler to post callbacks from download threads to the main thread; you'll need to marshal UI updates correctly and avoid ANR
- SQLite Database Persistence & Transactions — RemitDatabase uses SQLite to store task metadata and breakpoint offsets; understanding transaction isolation and cursor lifecycle is needed for custom DB impls or debugging state corruption
- Strategy Pattern (Pluggable Interfaces) — FileDownloader's strength is its customizable components (Connection, OutputStream, Database, etc.); understanding how to implement and register these interfaces is essential for adapting to different backends
- Random Access File & Sparse Writes — FileDownloadRandomAccessFile seeks to specific offsets to write chunks out of order; you need to understand file I/O patterns to avoid data corruption or performance cliffs
🔗Related repos
lingochamp/okdownload— Official successor project; FileDownloader defers all new features here and recommends it for new projectsJacksgong/filedownloader-okhttp3-connection— Official companion: plug-and-play OkHttp3 backend for FileDownloader's customizable connection interfaceArthurHub/Android-Fast-ImageLoader— Related Android image/resource loading library; similar multi-thread + cache + resume patternssquare/okhttp— HTTP client library commonly swapped into FileDownloader's connection layer for better controlgreenrobot/EventBus— Event-driven pub/sub often used alongside FileDownloader to decouple download callbacks from UI code
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for core download engine (FileDownloader.java and DownloadTaskManager.java)
The README explicitly states 'FileDownloader unit-test coverage is very low' and this is cited as the reason for redirecting new features to okdownload. Adding unit tests for core download logic (task queuing, breakpoint resume, multi-thread coordination) would improve code reliability and make the project maintainable for bug fixes. This directly addresses the stated weakness.
- [ ] Create src/test/java/com/liulishuo/filedownloader/services/ directory structure
- [ ] Add unit tests for DownloadTaskManager lifecycle (pause, resume, cancel operations)
- [ ] Add unit tests for multi-thread coordination and breakpoint resume logic in core download classes
- [ ] Add unit tests for FileDownloadConnection and connection pooling behavior
- [ ] Configure code coverage reporting in build.gradle and .travis.yml
Add GitHub Actions CI workflow to replace/supplement Travis CI for modern Android testing
The repo uses .travis.yml (outdated service) but modern Android projects use GitHub Actions for better integration. Create a workflow to run lint checks, unit tests, and build verification on pull requests. This improves contributor experience and catches regressions early.
- [ ] Create .github/workflows/android-ci.yml with gradle lint and build steps
- [ ] Add checkstyle validation step referencing checkstyle.xml (already present)
- [ ] Configure artifact uploads for build outputs and test reports
- [ ] Add workflow status badge to README.md
Document and add integration tests for SingleTask vs MultiTask download scenarios in demo/src/test/
The demo contains multiple activity classes (SingleTaskTestActivity.java, MultitaskTestActivity.java, HybridTestActivity.java) showcasing different usage patterns, but there are no corresponding integration tests. Adding tests that verify these scenarios work correctly would prevent regressions and serve as executable documentation.
- [ ] Create demo/src/androidTest/java/com/liulishuo/filedownloader/demo/ directory
- [ ] Add AndroidTest for single task download lifecycle (success, failure, pause/resume)
- [ ] Add AndroidTest for multitask parallel download with concurrent limits
- [ ] Add AndroidTest for hybrid scenarios with mixed task types
- [ ] Add assertions for notification callbacks in GlobalMonitor.java
🌿Good first issues
- Add unit tests for
FileDownloadDatabaseinterface and defaultRemitDatabaseimplementation inlibrary/src/test/(acknowledged gap: 'unit-test coverage is very low')—start with happy-path tests for insert/query breakpoint state. - Document the pluggable component pattern with a worked example: create a companion doc showing how to implement and register a custom
FileDownloadConnectionusing OkHttp3 (the okhttp3-connection repo exists but is external; inline example would help adoption). - Add a non-Android unit test suite for the multi-threading / connection pooling logic in the core downloader state machine (currently all tests depend on Android Context; isolate pure Java logic).
⭐Top contributors
Click to expand
Top contributors
- @Jacksgong — 52 commits
- [@Tianhua Ran](https://github.com/Tianhua Ran) — 44 commits
- @rantianhua — 1 commits
- @冉天华 — 1 commits
- @Niuchong — 1 commits
📝Recent commits
Click to expand
Recent commits
6237a8c— Merge pull request #1296 from rantianhua/fix/1295 (rantianhua)f1cbeff— fix: close automation redirects of HttpUrlConnection (Tianhua Ran)91228db— ci: upgrade to v1.7.8-SNAPSHOT for continue deploy (Jacksgong)c2ea399— ci: release v1.7.7 for fix some issues (Tianhua Ran)5d40c26— Merge pull request #1271 from lingochamp/fix/demo (Jacksgong)d216598— demo: avoid clear http text exception (Tianhua Ran)0e32777— demo: correct single task sample url (Tianhua Ran)cc58548— Merge pull request #1270 from lingochamp/fix/cast_exception (Jacksgong)7678313— fix: may throw cast exception in FileDownloadThreadPool (Tianhua Ran)15dc1f3— Merge pull request #1269 from lingochamp/revert-1266-fix/1152 (Jacksgong)
🔒Security observations
The FileDownloader project has several security concerns, primarily related to outdated dependencies, presence of sensitive files (keystore), and deprecated tooling. The build infrastructure is significantly outdated (Gradle 3.3.1, Bintray plugin v1.7.3), exposing the project to known vulnerabilities. The inclusion of a cryptographic keystore file in the repository is a critical security oversight. IDE configuration files should be excluded from version control. Immediate action is needed to update build tools, remove sensitive files, and modernize the dependency management strategy. The project appears to be in maintenance mode (per README mentioning okdownload as successor), but core security issues should still be addressed.
- High · Outdated Gradle Build Tools —
build.gradle. The project uses Gradle 3.3.1 (from 2018), which is significantly outdated and contains known security vulnerabilities. This version lacks security patches and modern dependency management features. Fix: Update to the latest stable Gradle version (8.x or later) to receive security patches and improvements. - High · Outdated Bintray Plugin —
build.gradle (classpath dependency). The gradle-bintray-plugin v1.7.3 is outdated and deprecated. Bintray was shut down in 2021, and this plugin is no longer maintained or receiving security updates. Fix: Migrate to Maven Central or an alternative artifact repository. Update build scripts to use current publishing plugins compatible with your chosen repository. - Medium · Sensitive Keystore File in Repository —
demo/filedownloaderdemo.jks. A Java keystore file (filedownloaderdemo.jks) is present in the demo module. Keystore files should never be committed to version control as they contain cryptographic keys and sensitive signing information. Fix: Remove the keystore file from version control immediately, invalidate any exposed keys, and regenerate new signing keys. Add *.jks to .gitignore and store the keystore securely outside the repository. - Medium · ProGuard Rules in Repository —
demo/proguard-rules.pro. The proguard-rules.pro file may contain mappings or configurations that could reveal code structure or sensitive class names in obfuscation rules. Fix: Review proguard-rules.pro to ensure no sensitive information is exposed. Keep obfuscation rules generic and avoid hardcoding sensitive names. - Low · IDE Configuration Files in Version Control —
.idea/. IntelliJ IDEA configuration files (.idea directory) are committed to the repository. These may contain local environment settings, passwords, or project-specific configurations. Fix: Add .idea/ directory to .gitignore to prevent committing IDE-specific configurations and sensitive local settings. - Low · Missing Security Headers and HTTPS Enforcement —
build.gradle (repositories block). The repository uses jcenter() which is deprecated and may not enforce HTTPS by default. Google's Maven repository should be preferred. Fix: Replace jcenter() with mavenCentral() or google(), and ensure all repositories use HTTPS endpoints explicitly.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.