RepoPilotOpen in app →

koral--/android-gif-drawable

Views and Drawable for displaying animated GIFs on Android

Mixed

Mixed signals — read the receipts

weakest axis
Use as dependencyConcerns

non-standard license (Other)

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.

  • Last commit 3mo ago
  • 13 active contributors
  • Other licensed
Show all 7 evidence items →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 76% of recent commits
  • Non-standard license (Other) — review terms
What would change the summary?
  • Use as dependency ConcernsMixed if: clarify license terms

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/koral--/android-gif-drawable?axis=fork)](https://repopilot.app/r/koral--/android-gif-drawable)

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/koral--/android-gif-drawable on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: koral--/android-gif-drawable

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/koral--/android-gif-drawable 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 — Mixed signals — read the receipts

  • Last commit 3mo ago
  • 13 active contributors
  • Other licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 76% of recent commits
  • ⚠ Non-standard license (Other) — review terms

<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 koral--/android-gif-drawable repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/koral--/android-gif-drawable.

What it runs against: a local clone of koral--/android-gif-drawable — 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 koral--/android-gif-drawable | Confirms the artifact applies here, not a fork | | 2 | License is still Other | Catches relicense before you depend on it | | 3 | Default branch dev exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 115 days ago | Catches sudden abandonment since generation |

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

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "koral--/android-gif-drawable(\\.git)?\\b" \\
  && ok "origin remote is koral--/android-gif-drawable" \\
  || miss "origin remote is not koral--/android-gif-drawable (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
  && ok "license is Other" \\
  || miss "license drift — was Other at generation time"

# 3. Default branch
git rev-parse --verify dev >/dev/null 2>&1 \\
  && ok "default branch dev exists" \\
  || miss "default branch dev no longer exists"

# 4. Critical files exist
test -f "android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawable.java" \\
  && ok "android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawable.java" \\
  || miss "missing critical file: android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawable.java"
test -f "android-gif-drawable/src/main/c/gif.h" \\
  && ok "android-gif-drawable/src/main/c/gif.h" \\
  || miss "missing critical file: android-gif-drawable/src/main/c/gif.h"
test -f "android-gif-drawable/src/main/c/jni.c" \\
  && ok "android-gif-drawable/src/main/c/jni.c" \\
  || miss "missing critical file: android-gif-drawable/src/main/c/jni.c"
test -f "android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawableBuilder.java" \\
  && ok "android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawableBuilder.java" \\
  || miss "missing critical file: android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawableBuilder.java"
test -f "android-gif-drawable/src/main/c/decoding.c" \\
  && ok "android-gif-drawable/src/main/c/decoding.c" \\
  || miss "missing critical file: android-gif-drawable/src/main/c/decoding.c"

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

android-gif-drawable is a high-performance Android library that renders animated GIFs using bundled GIFLib via JNI instead of the slower WebView or Movie classes. It provides drop-in Drawable and View components for seamless GIF playback, with frame-by-frame rendering control and efficient memory management through native code. Monorepo structure: android-gif-drawable/ is the main library module with src/main/c/ containing native C code (GIFLib wrapper + custom decoding/drawing/control logic), src/main/java/ for JNI bindings, and src/androidTest/ for instrumentation tests. CMake (CMakeLists.txt) orchestrates native builds; Gradle handles AAR packaging and Maven publication.

👥Who it's for

Android app developers building mobile applications that need to display animated GIFs efficiently without performance degradation. Particularly useful for apps requiring frame-level control (seeking, pausing) and developers who want better performance than Android's built-in Movie class.

🌱Maturity & risk

Production-ready and actively maintained. The library has reached version 1.2.31 on Maven Central, includes comprehensive AndroidTest instrumentation tests (AllocationByteCountTest, GifDrawableExceptionTest, etc.), runs CI through Bitrise, and has an OpenSSF Scorecard. Commits appear regular based on changelog presence and version stability.

Low risk for production use but single-maintainer (koral--) implies potential maintenance gaps. Native code dependency (GIFLib bundled in src/main/c/giflib/) requires NDK compilation and adds binary size. Minumum API level 17 is dated; no recent major breaking changes evident, but C code security requires monitoring (SECURITY.md exists, suggesting active security awareness).

Active areas of work

Actively maintained with recent version 1.2.31 published. Security posture is tracked (SECURITY.md, OpenSSF Scorecard badge). Snapshot builds available from dev branch via OSS Sonatype repository, indicating ongoing development. Library appears stable with focus on maintenance rather than major feature additions.

🚀Get running

git clone https://github.com/koral--/android-gif-drawable.git
cd android-gif-drawable
# Requires Android SDK, NDK (version specified in gradle), and CMake
# Open in Android Studio or build via Gradle:
./gradlew build

Daily commands: No server; this is a library. To test locally: ./gradlew connectedAndroidTest (runs instrumentation tests on emulator/device) or ./gradlew test (unit tests). Library is consumed via Gradle dependency in downstream Android projects.

🗺️Map of the codebase

  • android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawable.java — Core drawable class that manages GIF decoding, rendering, animation lifecycle, and serves as the primary entry point for displaying animated GIFs.
  • android-gif-drawable/src/main/c/gif.h — C header defining the native GIF decoder interface and data structures; all JNI bindings depend on these definitions.
  • android-gif-drawable/src/main/c/jni.c — JNI bridge layer connecting Java GifDrawable to native C decoding; handles memory management and callback marshalling.
  • android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawableBuilder.java — Factory for constructing GifDrawable instances with fluent API; encapsulates configuration and initialization logic.
  • android-gif-drawable/src/main/c/decoding.c — Core frame decoding implementation using giflib; handles progressive GIF parsing and frame extraction.
  • android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifImageView.java — Primary View subclass for embedding GifDrawable in layouts; handles attribute parsing and lifecycle integration.
  • android-gif-drawable/build.gradle — Gradle build configuration defining NDK integration, dependencies, and Maven publication; required for understanding library build process.

🛠️How to make changes

Add a new InputSource for custom data loading

  1. Create a new class implementing the InputSource interface (e.g., CustomInputSource) (android-gif-drawable/src/main/java/pl/droidsonroids/gif/InputSource.java)
  2. Implement required methods: seekTo(), read(), reset() to provide GIF data from your custom source (android-gif-drawable/src/main/java/pl/droidsonroids/gif/InputSource.java)
  3. Pass your InputSource to GifDrawableBuilder via builder().from(inputSource) (android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawableBuilder.java)
  4. Test with GifImageView or GifDrawable to verify frame rendering (android-gif-drawable/src/androidTest/java/pl/droidsonroids/gif/InputStreamTest.java)

Add animation event callbacks

  1. Implement the AnimationListener interface with onAnimationStart(), onFrameChanged(), onAnimationStop() (android-gif-drawable/src/main/java/pl/droidsonroids/gif/AnimationListener.java)
  2. Register listener via GifDrawable.addAnimationListener(yourListener) (android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawable.java)
  3. Use MultiCallback to manage multiple listeners if needed (android-gif-drawable/src/main/java/pl/droidsonroids/gif/MultiCallback.java)

Add custom bitmap transformation (e.g., corner radius)

  1. Create a Transform implementation (reference: CornerRadiusTransform) (android-gif-drawable/src/main/java/pl/droidsonroids/gif/transforms/Transform.java)
  2. Implement postProcess(Bitmap) method to apply frame-level bitmap operations (android-gif-drawable/src/main/java/pl/droidsonroids/gif/transforms/CornerRadiusTransform.java)
  3. Pass transform to GifDrawableBuilder via builder().transform(yourTransform) (android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawableBuilder.java)

Handle new GIF error scenarios

  1. Add new error code enum to GifError (mirrors native errors from gif.h) (android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifError.java)
  2. Update native C code (jni.c, decoding.c) to detect and return new error code (android-gif-drawable/src/main/c/jni.c)
  3. Map errno to GifIOException in GifDrawable or builder initialization (android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifIOException.java)
  4. Write integration test in androidTest to verify error handling (android-gif-drawable/src/androidTest/java/pl/droidsonroids/gif/GifDrawableExceptionTest.java)

🪤Traps & gotchas

CMake version and NDK version must match those in gradle/versions.gradle (check versions.ndk, versions.cmake variables). Native code compiled with '-Weverything' flag in debug builds—unused variable warnings may fail CI. ARM32 uses custom memset.arm.S assembly for performance; missing from other ABIs. JNI Bitmap allocation uses hardcoded ARGB_8888 format; transparency handling may differ from system WebView. Relinker dependency (com.getkeepsafe.relinker) required for dynamic .so loading; library won't work if this fails (check logcat). Consumer apps must include proguard rules or JNI signatures break under obfuscation.

🏗️Architecture

💡Concepts to learn

  • JNI (Java Native Interface) — Core mechanism in this library—Java GifDrawable calls native C code in jni.c to decode and render frames; understanding JNI signature conventions and lifecycle is essential for debugging crashes or extending functionality
  • GIF Interlacing and Frame Disposal — GIFLib handles interlaced GIF decoding (progressive rendering) and disposal methods (how frames replace prior frames); these affect animation correctness and performance in dispose.c and drawing.c
  • Android Bitmap Allocation via Native Memory — bitmap.c uses native allocation (malloc) then wraps with Android Bitmap object for efficient pixel buffer management; critical for avoiding GC pressure and OOM in animation loops
  • CMake Cross-Compilation for Android ABIs — CMakeLists.txt compiles C code for multiple ABIs (armeabi-v7a, arm64-v8a, x86, x86_64); this library includes ARM SIMD optimization (memset.arm.S) and conditional compilation flags for different architectures
  • Drawable Pattern (Android Framework) — GifDrawable extends Android Drawable, inheriting framework lifecycle (onBoundsChange, draw, getIntrinsicWidth/Height); understanding when draw() is called by layouting system is essential for animation synchronization
  • Frame Rate & Timing (GIF Delays) — GIFs encode per-frame delays in centiseconds; decoding.c parses these, and time.c manages animation timing; mismatch between system refresh rate (60Hz) and GIF frame delays requires interpolation logic
  • ProGuard/R8 Obfuscation & JNI Method Signatures — consumer-proguard-rules.pro must preserve exact Java method names because JNI uses string-based method lookup; obfuscation breaks native calls unless rules are correct
  • facebook/fresco — Production-grade image library for Android with GIF support via native decoders; direct alternative if you need broader image format support (WebP, HEIF)
  • bumptech/glide — Popular Android image loading library with GIF animation support via built-in decoders; easier integration via loader pattern but potentially slower than native GIFLib
  • square/picasso — Simpler image loading library for Android with GIF support; lightweight alternative if you don't need frame-level control
  • libgif/giflib — Upstream GIFLib source (bundled in this repo under src/main/c/giflib/); reference for bug fixes and GIF spec compliance
  • android/ndk-samples — Official Android NDK examples showing JNI patterns similar to this library's jni.c / bitmap.c interaction model

🪄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 instrumented tests for GifDrawableBuilder configuration edge cases

The GifDrawableBuilder.java class enables flexible GIF loading but lacks comprehensive instrumented tests. Currently, androidTest only has basic tests (GifViewDescriptorTest, InputStreamTest, etc.). The builder supports multiple initialization paths (file, resource, stream, URI) and configuration options that need thorough coverage to prevent regressions in builder state management and option combinations.

  • [ ] Create android-gif-drawable/src/androidTest/java/pl/droidsonroids/gif/GifDrawableBuilderTest.java
  • [ ] Add tests for each builder configuration path: fromFile(), fromResource(), fromInputStream(), fromUri()
  • [ ] Test builder option combinations: sampling size, input buffer size, and loop behavior
  • [ ] Add tests for builder validation (null inputs, invalid resources, closed streams)
  • [ ] Test builder reuse scenarios and state isolation between builds

Add unit tests for GifOptions and GifAnimationMetaData classes

GifOptions.java and GifAnimationMetaData.java are data/config classes that currently lack unit test coverage. These classes handle critical metadata about animations (frame delays, loop counts, disposal methods) and configuration parameters. Unit tests would ensure serialization, immutability guarantees, and edge cases are properly handled without requiring instrumentation.

  • [ ] Create android-gif-drawable/src/test/java/pl/droidsonroids/gif/GifOptionsTest.java
  • [ ] Create android-gif-drawable/src/test/java/pl/droidsonroids/gif/GifAnimationMetaDataTest.java
  • [ ] Test GifOptions: buffer size boundaries, sampling validation, loop flag combinations
  • [ ] Test GifAnimationMetaData: frame duration array edge cases, total duration calculation, disposal method handling
  • [ ] Add null/boundary value tests and equals/hashCode contracts if applicable

Add GitHub Actions workflow for native C code static analysis and memory safety checks

The repository contains significant native C code (src/main/c/) including custom giflib integration and JNI bindings, but only has a scorecards.yml workflow. There's no automated static analysis or memory safety verification for the C layer. Adding clang-tidy or similar tools to .github/workflows/ would catch common C vulnerabilities early and ensure code quality parity with Java tests.

  • [ ] Create .github/workflows/native-analysis.yml workflow file
  • [ ] Configure clang-tidy to scan src/main/c/*.c and *.h files with appropriate flags matching CMakeLists.txt
  • [ ] Add cppcheck as secondary static analyzer for additional coverage (memory leaks, buffer overflows)
  • [ ] Configure workflow to run on pull requests and report findings as check annotations
  • [ ] Document in CONTRIBUTING.md or README.md how contributors can run local analysis

🌿Good first issues

  • Add unit test coverage for src/main/c/control.c (animation control: start, stop, seek) — currently tested only in androidTest; pure logic tests in src/test/ would catch edge cases without emulator
  • Document the memory allocation strategy in src/main/c/bitmap.c for consumers concerned about OOM — add Javadoc explaining AllocationByteCountTest results and peak memory usage across frame counts
  • Create a minimal Kotlin example in a new examples/kotlin-sample/ directory using GifDrawable with Jetpack Compose (currently only Java examples visible in docs)

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 7202f5a — Release 1.2.31 (koral--)
  • 2e9e828 — Remove Kotlin dependency from library module (koral--)
  • e5f523a — Release 1.2.30 (koral--)
  • d8ecdb5 — Update AssertJ dependency and refactor tests to use updated assertions (koral--)
  • 1fdd5af — Update dependency versions (koral--)
  • 083a8f7 — Remove extra file descriptor close in openNativeFileDescriptor (koral--)
  • 66d1156 — Update actions in scorecards (#854) (koral--)
  • 95aa167 — Update scorecard analysis workflow (#853) (koral--)
  • 7a4ee0f — Add support 16 KB page sizes for Android 15 (#847) (koral--)
  • e9ca4a1 — Add binary compatibility checker (#836) (koral--)

🔒Security observations

The android-gif-drawable library demonstrates generally sound security practices with proper NDK configuration, ProGuard rules, and secure build flags for release builds. However, critical concerns exist around native C code security, particularly in GIF decoding routines which could be vulnerable to malformed input attacks (buffer overflows, integer overflows). The incomplete dependency information in the provided build.gradle prevents full assessment. No hardcoded secrets, SQL injection, XSS, or infrastructure misconfigurations were identified. Recommended actions: (1) Conduct comprehensive security testing of native code with fuzzing, (2) Implement stricter input validation in GIF parsing, (3) Provide complete dependency manifest for vulnerability scanning, (4) Enhance security update policy for older versions.

  • Medium · Native Code Security - Missing Bounds Checking — android-gif-drawable/src/main/c/bitmap.c, android-gif-drawable/src/main/c/drawing.c, android-gif-drawable/src/main/c/decoding.c. The C codebase includes custom GIF decoding (giflib) with potential buffer overflow risks. The custom implementation in bitmap.c, drawing.c, and decoding.c may lack sufficient bounds checking on decoded GIF data, particularly with malformed GIF files. Fix: Conduct thorough code review and fuzzing of C code with malformed GIF inputs. Implement additional bounds checking, use safe memory functions, and consider AddressSanitizer (ASan) during development.
  • Medium · Incomplete Dependency Information — android-gif-drawable/build.gradle. The build.gradle file is truncated in the provided content, cutting off the 'org.khron' dependency which appears incomplete. This could mask missing or vulnerable dependencies that aren't fully visible in the analysis. Fix: Provide complete dependency manifest and run dependency vulnerability scanning tools (e.g., OWASP Dependency-Check, Snyk) against all dependencies.
  • Low · Debug Symbols in Release Builds — android-gif-drawable/build.gradle (CMake configuration). The build configuration includes '-g0' flag for release builds to remove debug symbols, but this is not enforced at all stages. Debug builds include '-g' flag which could expose internal information. Fix: Ensure debug symbols are completely stripped from release APKs/AABs. Configure ProGuard/R8 rules to enable shrinking and obfuscation for production builds.
  • Low · Missing ProGuard Configuration for Native Bindings — android-gif-drawable/consumer-proguard-rules.pro. While a consumer-proguard-rules.pro file exists, JNI method names must be preserved. If not properly configured, obfuscation could break the JNI bindings to native code. Fix: Verify that consumer-proguard-rules.pro includes keep rules for JNI callback methods and native interface classes (e.g., GifDecoder, GifInfoHandle).
  • Low · Limited Security Policy — SECURITY.md. The SECURITY.md policy only guarantees patches for the latest version. Users on older versions may face unpatched security vulnerabilities. Fix: Consider supporting at least the last 2-3 major versions with security patches. Provide clear deprecation timeline for older versions.
  • Low · Potential Integer Overflow in Image Dimensions — android-gif-drawable/src/main/c/bitmap.c, android-gif-drawable/src/main/java/pl/droidsonroids/gif/GifDrawable.java. GIF files contain width/height fields that could be manipulated. Without proper validation, these could lead to integer overflows when calculating buffer sizes in bitmap allocation. Fix: Implement strict validation of GIF dimensions before allocation. Check for unreasonable sizes and potential overflow conditions (e.g., width * height * bytesPerPixel).

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 · koral--/android-gif-drawable — RepoPilot