| name | android-bug-reproduce |
| description | Reproduce and debug Android bugs on an emulator using ADB. Covers emulator setup, test data seeding, UI navigation via uiautomator, log capture, and screenshots. Use when the user asks to reproduce a bug, debug an issue on an emulator, or investigate an Android crash/behavior. |
Android Bug Reproduction on Emulator
Systematically reproduce and investigate Android bugs using ADB and the emulator.
Prerequisites
- Android SDK installed with
emulator and adb on PATH
- At least one AVD configured (check with
emulator -list-avds)
- A debug APK (build with
./gradlew assembleDebug if needed)
Workflow
Step 1: Start the emulator
Check for a running emulator first:
adb devices
If none is running, start one:
emulator -list-avds
emulator -avd <avd_name> -no-snapshot-load &
Wait for the device to be ready:
adb wait-for-device
adb shell getprop sys.boot_completed
Step 2: Install the debug APK
adb install -r app/build/outputs/apk/debug/app-debug.apk
Step 3: Seed test data (if needed)
For features that require existing data (e.g., chord sheets, favorites), seed SharedPreferences directly:
adb shell am force-stop com.baijum.ukufretboard
adb shell run-as com.baijum.ukufretboard sh -c 'cat > shared_prefs/<pref_file>.xml << '\''XMLEOF'\''
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<map>
<!-- Your test data here -->
</map>
XMLEOF'
Common preference files:
| File | Contents |
|---|
chord_sheets.xml | Saved songs/chord sheets (JSON list) |
favorites.xml | Favorited chords |
app_settings.xml | App settings |
Example — seed a chord sheet:
adb shell run-as com.baijum.ukufretboard sh -c 'cat > shared_prefs/chord_sheets.xml << '\''XMLEOF'\''
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<map>
<string name="chord_sheets_json">[{"id":"test-1","title":"Test Song","artist":"Test","content":"[C]Hello [Am]world\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8\nLine 9\nLine 10","strumPatternName":"","labels":[],"createdAt":1700000000000,"updatedAt":1700000000000}]</string>
</map>
XMLEOF'
Step 4: Launch the app and navigate
adb shell am start -n com.baijum.ukufretboard/.MainActivity
Find UI element coordinates with uiautomator
Dump the current UI tree to find element bounds:
adb shell uiautomator dump /sdcard/ui.xml
adb shell cat /sdcard/ui.xml | head -c 5000
Search for a specific element by content-description or text:
adb shell uiautomator dump /sdcard/ui.xml
adb pull /sdcard/ui.xml /tmp/ui.xml
grep -o 'content-desc="[^"]*"[^/]*bounds="[^"]*"' /tmp/ui.xml
Common navigation actions
adb shell uiautomator dump /sdcard/ui.xml
adb shell input tap <x> <y>
adb shell input tap 540 960
adb shell input keyevent 4
adb shell input text "hello"
adb shell input swipe 540 1500 540 500 300
Step 5: Add instrumentation logging
When the root cause isn't obvious, add temporary Log.d statements to the relevant code:
import android.util.Log
Log.d("DEBUG_<issue>", "state: autoScrolling=$autoScrolling, scrollValue=${scrollState.value}")
Rebuild and reinstall:
./gradlew assembleDebug && adb install -r app/build/outputs/apk/debug/app-debug.apk
Step 6: Capture and filter logs
adb logcat -c
adb logcat -s "DEBUG_<issue>:D" &
adb logcat -s "DEBUG_<issue>:D" > /tmp/debug_log.txt &
Reproduce the bug, then stop logcat and analyze the output.
Step 7: Take screenshots
adb shell screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png /tmp/screenshot_before.png
For before/after comparison:
adb shell screencap -p /sdcard/before.png
adb pull /sdcard/before.png /tmp/before.png
adb shell screencap -p /sdcard/after.png
adb pull /sdcard/after.png /tmp/after.png
Step 8: Clean up
Remove debug logging before committing:
grep -rn "DEBUG_<issue>" app/src/main/java/
Remove the Log.d lines and the import android.util.Log if no longer needed.
Tips
- Prefer seeding data over UI automation — writing SharedPreferences XML is far more reliable than tapping through UI to create test data.
- Use
uiautomator dump before every tap — screen layouts change between devices and orientations; never hardcode coordinates from memory.
- Keep debug tags unique — include the issue number (e.g.,
DEBUG_issue41) so logs don't mix with other debugging sessions.
- Force-stop before seeding — SharedPreferences are cached in memory; the app must be stopped before writing XML files.