Skip to content
Development
Skill

/android-debugging

Use when debugging Android or KMP issues — Android-specific techniques covering Logcat, ADB, ANR traces, R8 stack trace decoding, memory leaks, Gradle build failures, and Compose recomposition bugs, on a root-cause-first foundation.

BOOST
From plugin
android-skills
16221 skills
Install
$ npx -y skills add rcosteira79/android-skills --skill android-debugging --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/android-debugging

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when debugging Android or KMP issues — Android-specific techniques covering Logcat, ADB, ANR traces, R8 stack trace decoding, memory leaks, Gradle build failures, and Compose recomposition bugs, on a root-cause-first foundation.

SKILL.md

android-debugging.SKILL.md
name: android-debugging
description: >
  Use when debugging Android or KMP issues — Android-specific techniques covering Logcat, ADB,
  ANR traces, R8 stack trace decoding, memory leaks, Gradle build failures, and Compose
  recomposition bugs, on a root-cause-first foundation.

Android Debugging

Overview

Android-specific evidence-gathering and investigation techniques on a root-cause-first foundation.

**Root-cause-first foundation:**

  • **No fix before the root cause is found.** Investigate first — reproduce, gather evidence (observed values, not assumed), trace the cause. Patching a symptom you don't understand creates two bugs.
  • **Three failed guesses ⇒ stop and question the architecture** rather than guessing again.

The Android-specific tools below serve that investigation. *Optional:* if you run a dedicated debugging-discipline skill (e.g. `superpowers:systematic-debugging` or `ace:systematic-debugging`), this layers on top of it — but it requires none.

Evidence-Gathering by Problem Type

Crashes & Exceptions

# Stream crash logs filtered by app package
adb logcat --pid=$(adb shell pidof -s com.example.app)

# Save full logcat to file for analysis
adb logcat -d > crash_log.txt

# Filter by tag
adb logcat -s "YourTag:E"

Key logcat log levels: `V` (verbose) `D` (debug) `I` (info) `W` (warn) `E` (error) `F` (fatal)

Read the **full stack trace** — the root cause is usually at the bottom of the `Caused by:` chain, not the top-level exception.

ANR (Application Not Responding)

ANRs mean the main thread was blocked. Evidence:

# Pull ANR trace from device
adb pull /data/anr/traces.txt ./anr_traces.txt

# Or stream while reproducing
adb logcat -s "ActivityManager:E" | grep -A 30 "ANR in"

Look for: `main` thread in state `MONITOR` (waiting for a lock) or blocking I/O on `main`. Trace backward to find what holds the lock.

**Common causes:** Database/network call on main thread, `runBlocking` on main thread, deadlock between coroutine scopes.

Memory Leaks

Add [LeakCanary](https://square.github.io/leakcanary/) to `debugImplementation`. It surfaces leak traces automatically in a notification.

Read the leak trace top-to-bottom: the first bold line is the leaking object, the path shows what's holding the reference. Fix by clearing the reference in the appropriate lifecycle callback.

# Dump heap manually for Android Profiler analysis
adb shell am dumpheap com.example.app /data/local/tmp/heap.hprof
adb pull /data/local/tmp/heap.hprof ./heap.hprof

Performance Trace Investigation (Perfetto)

For bottleneck investigation across CPU, graphics, I/O, IPC, memory, or power — beyond what Logcat and ANR traces show — capture a Perfetto trace and query it with SQL.

**Measure before you fix.** For performance regressions, logs usually mislead — capture a *baseline* measurement before changing anything, then bisect against it. A trace tells you where time goes; only a comparison against a known-good baseline tells you what actually regressed.

# Capture a trace (system-level, all categories)
adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace.pftrace \
  <<'EOF'
buffers { size_kb: 65536 }
data_sources { config { name: "linux.ftrace" } }
data_sources { config { name: "android.surfaceflinger.frame" } }
duration_ms: 10000
EOF

adb pull /data/misc/perfetto-traces/trace.pftrace ./

Then open the trace at https://ui.perfetto.dev and run SQL against it (`SELECT name, dur FROM slice WHERE dur > 16e6` for frames slower than 16ms, etc.).

For an agent-driven workflow — translating an investigation intent (jank, slow startup, battery drain) into the right Perfetto SQL and iterating across the trace — see Google's [`perfetto-sql`](https://github.com/android/skills/tree/main/profilers/perfetto-sql) and [`perfetto-trace-analysis`](https://github.com/android/skills/tree/main/profilers/perfetto-trace-analysis) skills (`android skills list` to check for a local install; `android skills add perfetto-sql perfetto-trace-analysis` otherwise). They provide Domain Hints (CPU/Graphics/I/O/IPC/Memory/Power), a mandatory scratchpad chain-of-evidence pattern, and `GLOB`-over-`LIKE` query rules.

R8 / ProGuard — Obfuscated Stack Traces

Release crash stack traces are obfuscated. Decode them with the mapping file generated at build time.

# retrace a crash (AGP 7+)
./gradlew :app:retrace --stacktrace-file crash.txt

# Or use the retrace CLI directly
java -jar retrace.jar mapping.txt crash.txt

Mapping files are in `app/build/outputs/mapping/<variant>/mapping.txt`. Always archive them alongside release builds.

If a class is unexpectedly removed or renamed, add a `-keep` rule in `proguard-rules.pro` and verify with:

./gradlew :app:assembleRelease
# Then inspect: app/build/outputs/mapping/release/usage.txt (removed) and seeds.txt (kept)

For the **inverse problem** — reading obfuscated third-party code or decoding a stack trace from a library where the mapping file isn't yours — `retrace` doesn't apply. Use `jadx --deobf` (consistent renames across the decompiled output) or `jadx --deobf-map` (when the SDK ships a mapping). The [`android-reverse-engineering` plugin](https://github.com/SimoneAvogadro/android-reverse-engineering-skill) covers the full workflow including the anchor-via-strings strategy for navigating obfuscated code by string literals and framework class names that survive obfuscation (check if it's already installed locally first — it ships as `android-reverse-engineering:*` skills).

Gradle Build Failures

Read the error from the **bottom up** — Gradle wraps errors in multiple layers.

Common patterns:

| Error | Investigation | |-------|--------------| | `Manifest merger failed` | Check `app/build/intermediates/merged_manifests/` for the merged output; look for conflicting `android:` attributes | | `Duplicate class` | Run `./gradlew dependencies` and look for the same class in multiple

Read more
Ships withandroid-skills

Android & KMP development skills for Claude Code, Codex, and Copilot CLI — architecture, Compose, coroutines, flows, networking, persistence, dependency injection, testing, debugging, and Gradle.

Get the whole plugin

Other skills on android-skills.