RepoPilotOpen in app →

danikula/AndroidVideoCache

Cache support for any video player with help of single line

Mixed

Stale — last commit 3y ago

weakest axis
Use as dependencyMixed

last commit was 3y ago; top contributor handles 91% of recent commits

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 8 active contributors
  • Apache-2.0 licensed
  • CI configured
Show all 6 evidence items →
  • Tests present
  • Stale — last commit 3y ago
  • Single-maintainer risk — top contributor 91% of recent commits
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days

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 "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/danikula/androidvideocache?axis=fork)](https://repopilot.app/r/danikula/androidvideocache)

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/danikula/androidvideocache on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: danikula/AndroidVideoCache

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:

  1. 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.
  2. 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.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/danikula/AndroidVideoCache 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

WAIT — Stale — last commit 3y ago

  • 8 active contributors
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 3y ago
  • ⚠ Single-maintainer risk — top contributor 91% 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 danikula/AndroidVideoCache repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/danikula/AndroidVideoCache.

What it runs against: a local clone of danikula/AndroidVideoCache — 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 danikula/AndroidVideoCache | 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 ≤ 1181 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>danikula/AndroidVideoCache</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of danikula/AndroidVideoCache. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/danikula/AndroidVideoCache.git
#   cd AndroidVideoCache
#
# 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 danikula/AndroidVideoCache and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "danikula/AndroidVideoCache(\\.git)?\\b" \\
  && ok "origin remote is danikula/AndroidVideoCache" \\
  || miss "origin remote is not danikula/AndroidVideoCache (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/danikula/videocache/HttpProxyCacheServer.java" \\
  && ok "library/src/main/java/com/danikula/videocache/HttpProxyCacheServer.java" \\
  || miss "missing critical file: library/src/main/java/com/danikula/videocache/HttpProxyCacheServer.java"
test -f "library/src/main/java/com/danikula/videocache/ProxyCache.java" \\
  && ok "library/src/main/java/com/danikula/videocache/ProxyCache.java" \\
  || miss "missing critical file: library/src/main/java/com/danikula/videocache/ProxyCache.java"
test -f "library/src/main/java/com/danikula/videocache/HttpUrlSource.java" \\
  && ok "library/src/main/java/com/danikula/videocache/HttpUrlSource.java" \\
  || miss "missing critical file: library/src/main/java/com/danikula/videocache/HttpUrlSource.java"
test -f "library/src/main/java/com/danikula/videocache/file/FileCache.java" \\
  && ok "library/src/main/java/com/danikula/videocache/file/FileCache.java" \\
  || miss "missing critical file: library/src/main/java/com/danikula/videocache/file/FileCache.java"
test -f "library/src/main/java/com/danikula/videocache/SourceInfo.java" \\
  && ok "library/src/main/java/com/danikula/videocache/SourceInfo.java" \\
  || miss "missing critical file: library/src/main/java/com/danikula/videocache/SourceInfo.java"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1181 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1151d)"
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/danikula/AndroidVideoCache"
  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).

</details>

TL;DR

AndroidVideoCache is an HTTP proxy server library that transparently caches video streams to disk during playback, allowing any Android VideoView, MediaPlayer, or ExoPlayer to support offline playback and resume from cache without re-downloading. It wraps the original video URL and serves cached chunks via a local proxy, eliminating redundant downloads when the same video is played multiple times. Single-module Maven/Gradle library: library/src/main contains all production code under com/danikula/videocache/, with core proxy logic in HttpProxyCacheServer.java, disk storage abstraction in file/FileCache.java, and HTTP source handling in HttpUrlSource.java. Entry point for users is the single HttpProxyCacheServer instance that intercepts requests and delegates to Source implementations (HttpUrlSource for remote, FileCache for local).

👥Who it's for

Android developers building media playback apps (news apps, streaming clients, educational platforms) who need to reduce bandwidth costs and enable offline viewing without modifying their existing player code—works as a drop-in proxy layer.

🌱Maturity & risk

Production-ready and stable: published on jcenter with version 2.7.1, uses Travis CI for continuous builds, and implements proper error handling via ProxyCacheException. However, the repo shows minimal recent activity (commit history not provided), suggesting it's feature-complete but not actively developed—suitable for production use but may lack bleeding-edge fixes.

Moderate risk: single-maintainer library (danikula) with no visible test suite in the file listing despite 165K lines of Java code, which is concerning for a caching system handling I/O. Known limitation: explicitly does not support streaming protocols (DASH, HLS, SmoothStreaming)—only direct URLs work. Dependency on javax.servlet and Android platform versions could limit forward compatibility.

Active areas of work

No active development visible from file timestamps. The repo appears stable at version 2.7.1 with no pending work indicated in the provided metadata—it is a mature, feature-frozen library.

🚀Get running

git clone https://github.com/danikula/AndroidVideoCache.git
cd AndroidVideoCache
./gradlew build

Then include in your Android project: dependencies { implementation 'com.danikula:videocache:2.7.1' } (available on jcenter; use library/ folder for local development).

Daily commands:

./gradlew assembleDebug          # Build library AAR
./gradlew test                   # Run tests (if present)
./gradlew connectedAndroidTest   # Run instrumented tests

No runnable sample app structure visible in file list; integration is done by consuming the library artifact.

🗺️Map of the codebase

  • library/src/main/java/com/danikula/videocache/HttpProxyCacheServer.java — Entry point and primary API for the caching system; manages the HTTP proxy server lifecycle and client connections.
  • library/src/main/java/com/danikula/videocache/ProxyCache.java — Core abstraction that coordinates caching logic between source, cache storage, and HTTP responses.
  • library/src/main/java/com/danikula/videocache/HttpUrlSource.java — Handles remote HTTP streaming and source metadata retrieval; critical for video data acquisition.
  • library/src/main/java/com/danikula/videocache/file/FileCache.java — Manages disk-based cache storage with random access support; implements the cache persistence layer.
  • library/src/main/java/com/danikula/videocache/SourceInfo.java — Data model for video metadata (length, MIME type, headers); essential for proper cache behavior.
  • library/src/main/java/com/danikula/videocache/Config.java — Configuration builder for cache behavior (disk limits, headers, custom sources); defines all tunable parameters.
  • library/build.gradle — Library build configuration; declares dependencies and module structure.

🛠️How to make changes

Add a Custom Video Source

  1. Create a new class implementing the Source interface in library/src/main/java/com/danikula/videocache/ (library/src/main/java/com/danikula/videocache/Source.java)
  2. Implement open(long offset) to return an InputStream from your source, length() for total bytes, and close() for cleanup (library/src/main/java/com/danikula/videocache/HttpUrlSource.java)
  3. Pass your Source implementation to Config.Builder.sourceInfoStorage() or directly to ProxyCache constructor (library/src/main/java/com/danikula/videocache/Config.java)

Configure Disk Cache Size Limits

  1. Create a Config.Builder and choose a DiskUsage strategy from library/src/main/java/com/danikula/videocache/file/ (library/src/main/java/com/danikula/videocache/Config.java)
  2. For total file count limit, use TotalCountLruDiskUsage; for size limit, use TotalSizeLruDiskUsage (library/src/main/java/com/danikula/videocache/file/TotalCountLruDiskUsage.java)
  3. Pass diskUsage strategy via Config.Builder.diskUsage(diskUsage) and build() (library/src/main/java/com/danikula/videocache/Config.java)
  4. Instantiate HttpProxyCacheServer with your config in Application.onCreate() (sample/src/main/java/com/danikula/videocache/sample/App.java)

Monitor Cache Progress

  1. Implement the CacheListener interface with onCacheAvailable(file, url, percentsAvailable) and onCacheUnavailable() (library/src/main/java/com/danikula/videocache/CacheListener.java)
  2. Register listener via HttpProxyCacheServer.registerCacheListener(listener, url) (library/src/main/java/com/danikula/videocache/HttpProxyCacheServer.java)
  3. Update UI progress bars or download indicators in onCacheAvailable() callback (sample/src/main/java/com/danikula/videocache/sample/VideoFragment.java)

Add Custom HTTP Headers

  1. Implement HeaderInjector interface in library/src/main/java/com/danikula/videocache/headers/ (library/src/main/java/com/danikula/videocache/headers/HeaderInjector.java)
  2. Override injectHeaders(url) to return a map of header names to values (e.g., User-Agent, Authorization) (library/src/main/java/com/danikula/videocache/headers/HeaderInjector.java)
  3. Pass your HeaderInjector to Config.Builder.headerInjector(injector) (library/src/main/java/com/danikula/videocache/Config.java)

🪤Traps & gotchas

Singleton requirement: HttpProxyCacheServer must be a single shared instance across entire app (mentioned in README)—creating multiple instances will cause port conflicts and cache inconsistency. Direct URLs only: library internally validates that URLs are direct media links; proxying DASH/HLS manifests will silently fail. Localhost binding: proxy binds to 127.0.0.1 only—will not work for cross-process or inter-device requests. File descriptor leaks: FileCache uses RandomAccessFile—ensure proper closure or face fd exhaustion on long-running apps. No explicit lifecycle management: HttpProxyCacheServer has no documented shutdown() method—lifecycle tied to application death.

🏗️Architecture

💡Concepts to learn

  • HTTP Range Requests (206 Partial Content) — HttpProxyCacheServer uses HTTP 206 responses to serve cached chunks and resume interrupted downloads—essential for efficient video streaming
  • Least Recently Used (LRU) Eviction — TotalSizeLruDiskUsage and TotalCountLruDiskUsage implement LRU cache eviction—core algorithm for managing disk space limits
  • Local HTTP Proxy Pattern — The library wraps real URLs with a local proxy (localhost:PORT)—transparent to the video player, allowing intercept and caching without player modification
  • Random Access File I/O — FileCache uses RandomAccessFile to support seeking within cached content—videos can be resumed from any position without re-downloading from start
  • Socket/Port Binding for Localhost — HttpProxyCacheServer binds to an available localhost port dynamically—requires understanding of port conflicts, firewall rules, and loopback interface behavior
  • Thread-safe Singleton Pattern — HttpProxyCacheServer must be initialized once and shared app-wide—the design enforces singleton semantics to avoid cache duplication and port conflicts
  • Callback/Listener Pattern for Progress — CacheListener interface allows UI updates during download—common pattern for notifying about long-running I/O operations
  • google/ExoPlayer — Official Google media player library with built-in caching support—the recommended modern alternative for new projects
  • square/okhttp — HTTP client with transparent response caching—could be used as alternative transport layer for HttpUrlSource
  • danikula/AndroidVideoCache-exoPlayer — Official fork/branch of this repo specifically optimized for ExoPlayer integration (mentioned in README)
  • facebook/cache — Facebook's flexible caching library for Android—provides disk/memory cache abstraction similar to this project's Cache interface
  • JakeWharton/DiskLruCache — Standalone LRU disk cache implementation—demonstrates similar FileCache / LruDiskUsage patterns used here

🪄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 unit tests for ProxyCache and HttpProxyCache core caching logic

The library lacks visible test coverage for core caching mechanisms. ProxyCache.java and HttpProxyCache.java are critical components but there's no test directory visible in the file structure. These classes handle cache read/write, byte range requests, and source streaming - essential functionality that should be regression-tested.

  • [ ] Create library/src/test/java/com/danikula/videocache/ directory structure
  • [ ] Add ProxyCacheTest.java with tests for cache read/write operations, concurrent access, and exception handling
  • [ ] Add HttpProxyCacheTest.java with tests for HTTP header parsing, range requests, and proxy behavior
  • [ ] Add tests for FileCache.java covering disk storage operations and LRU eviction policies
  • [ ] Integrate test execution into library/build.gradle with testInstrumentationRunner configuration

Add GitHub Actions CI workflow to replace Travis CI

.travis.yml exists but Travis CI has undergone significant changes (free tier limitations). Modern GitHub Actions provides better integration, faster feedback, and supports matrix testing across API levels. This modernizes the CI/CD pipeline and ensures contributors get timely feedback on PRs.

  • [ ] Create .github/workflows/build.yml for Android library build and unit tests
  • [ ] Add matrix strategy to test against multiple Android API levels (minSdkVersion through latest stable)
  • [ ] Include Gradle cache to speed up builds
  • [ ] Add instrumented tests step for sample app on Android emulator
  • [ ] Consider deprecating or removing .travis.yml after validation

Document custom Source implementation with example and tests

Source.java is an extension point for custom data sources, but the README only mentions HttpUrlSource. The sourcestorage/ and headers/ packages suggest advanced customization capabilities, but there's no concrete example or guide. Adding documentation for ByteArraySource usage patterns and creating a sample custom source would help contributors understand the plugin architecture.

  • [ ] Add 'Implementing Custom Sources' section to README.md with code example
  • [ ] Create sample/src/main/java/com/danikula/videocache/sample/CustomSource.java with a practical example (e.g., local file source or encrypted stream)
  • [ ] Add unit test sample/src/test/java showing how to test custom Source implementations
  • [ ] Document HeaderInjector interface usage with example for custom authentication headers
  • [ ] Update README table of contents to reference the new Custom Sources section

🌿Good first issues

  • Add unit tests for library/src/main/java/com/danikula/videocache/file/FileCache.java—currently no test coverage visible for disk I/O and random access operations, critical for reliability
  • Document cache clearing and reset behavior: add public methods and Javadoc to HttpProxyCacheServer for clearing cache, since current API doesn't expose cache invalidation
  • Create examples for custom Source implementations in library/src/main/java/com/danikula/videocache/Source.java—add a sample LocalFileSource and ByteArraySource documentation showing how to extend for non-HTTP sources

Top contributors

Click to expand

📝Recent commits

Click to expand
  • fe52f3c — Merge pull request #183 from imalhasaranga/master (danikula)
  • f02351b — :package: release 2.7.1 (danikula)
  • 36fea1c — fix tests (danikula)
  • 757317f — typo in the ReadMe.md (imalhasaranga)
  • acdf747 — #20: headers injector (lucas34)
  • 89ab593 — notice about exoPlayer demo in exoPlayer branch (danikula)
  • 1b597ec — :package: release 2.7.0 (danikula)
  • 7e48955 — fix tests (danikula)
  • 355e83b — #88: ignore ArrayIndexOutOfBoundsException on Android L while disconnecting connection (danikula)
  • c300b2e — :tada: fix #28: ignore system proxy for localhost requests (danikula)

🔒Security observations

  • High · Outdated Gradle Build Tool — build.gradle (classpath 'com.android.tools.build:gradle:2.3.1'). The project uses Gradle 2.3.1 from 2016, which is severely outdated and contains multiple known security vulnerabilities. This version lacks security patches and modern dependency resolution features. Fix: Update to the latest stable Gradle version (currently 8.x). Update Android Gradle Plugin to at least 7.4.0 or higher for security patches and improved dependency management.
  • High · No Dependency Pinning or Lock File — build.gradle (repositories configuration). The build.gradle uses only jcenter() repository without explicit version pinning for transitive dependencies. This creates supply chain risk where dependencies could be compromised or unexpected versions could be resolved. Fix: Use gradle.lockfile for dependency locking, explicitly pin dependency versions, migrate from deprecated jcenter() to mavenCentral() or other secure repositories, and implement dependency verification.
  • High · Use of Deprecated jcenter Repository — build.gradle (allprojects repositories section). jcenter() repository was sunset by JFrog in 2021. Using deprecated repositories increases risk of: outdated packages, compromised artifacts, and build failures. This is a known attack vector. Fix: Replace jcenter() with mavenCentral() or other maintained repositories. Update all build files and verify all dependencies are available in the new repository.
  • Medium · Potential HTTP Proxy Cache Information Disclosure — library/src/main/java/com/danikula/videocache/HttpProxyCache.java, HttpUrlSource.java, HttpProxyCacheServer.java. HttpProxyCache and related components cache video content via HTTP proxy. Without proper validation, this could lead to information disclosure, man-in-the-middle attacks, or serving stale/poisoned content if HTTPS is not enforced. Fix: Ensure HTTPS is enforced for all remote sources, implement certificate pinning, validate SSL/TLS certificates properly, and add integrity checks for cached content. Review header injection mechanisms for security headers.
  • Medium · SQL Injection Risk in Database Source Storage — library/src/main/java/com/danikula/videocache/sourcestorage/DatabaseSourceInfoStorage.java. DatabaseSourceInfoStorage likely uses SQLite to store source information. If user-controlled input (URLs, file names) is concatenated into SQL queries without parameterization, it could be vulnerable to SQL injection. Fix: Use parameterized queries (prepared statements) exclusively. Never concatenate user input into SQL strings. Review all database interactions for proper input validation and sanitization.
  • Medium · File Traversal Risk in FileNameGenerator — library/src/main/java/com/danikula/videocache/file/Md5FileNameGenerator.java, FileCache.java, FileNameGenerator.java. Md5FileNameGenerator and FileCache may be vulnerable to path traversal attacks if the source URL or file name is not properly validated before generating cache file paths. Fix: Validate all inputs before generating file paths. Use canonicalization to resolve paths and ensure they stay within the intended cache directory. Implement strict path validation checks.
  • Medium · No Input Validation on HTTP Headers — library/src/main/java/com/danikula/videocache/headers/HeaderInjector.java, EmptyHeadersInjector.java. HeaderInjector and EmptyHeadersInjector may allow injection of malicious HTTP headers if user-provided headers are not properly validated and sanitized. Fix: Implement strict validation for all HTTP headers. Reject headers containing line breaks, null bytes, or other special characters that could lead to header injection attacks. Use an allowlist of acceptable headers.
  • Low · Missing Runtime Permissions Documentation — library/src/main/AndroidManifest.xml, sample/src/main/AndroidManifest.xml. The library requires network and file system access. AndroidManifest.xml should clearly document required permissions, and runtime permission handling should be implemented for Android 6.0+. Fix: Ensure all required permissions are declared with clear justification. Implement runtime permission requests for dangerous permissions. Document permission requirements in README.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · danikula/AndroidVideoCache — RepoPilot