Debugging React Native / Expo Apps on Android with ADB
A practical cheat sheet for debugging React Native and Expo Android apps using adb. Covers raw log streams, PID and tag filtering, crash and ANR detection, Bluetooth LE debugging, Hermes/JS error tracing, and saving logs to files - with Bash and PowerShell examples.
A practical, copy‑pasteable guide for debugging React Native / Expo Android apps when Metro is silent or the app crashes (e.g., during Bluetooth operations). It covers raw log streams, app‑scoped filters, crash/ANR views, BLE‑focused logging, Hermes/JS errors, and saving sessions to files — with both bash andPowerShell examples.
📦Prerequisites
- Android Platform Tools installed and on your PATH (
adb version). - Device connected and authorized (
adb devicesshowsdevice). - Know your package name (Expo Go vs Dev Build differ).
⚡Quick checks
- 1List packages and find yoursbash
# Bash (Linux/macOS/Git Bash) adb shell pm list packages | grep -i yourappshell# PowerShell (Windows) adb shell pm list packages | Select-String -Pattern yourapp - 2Get your app PID (used for tight filters)bash
adb shell pidof -s com.yourcompany.yourappshelladb shell pidof -s com.yourcompany.yourapp
com.company.app. Classic Expo Go uses host.exp.exponent.🌊See everything (raw firehose)
adb logcat -v time# Clear old logs first
adb logcat -c🎯App‑scoped logging (PID & TAG filters)
- 1Filter by PID (recommended)bash
PID=$(adb shell pidof -s com.yourcompany.yourapp); adb logcat --pid=$PID -v timeshell$pid = adb shell pidof -s com.yourcompany.yourapp adb logcat --pid=$pid -v time - 2React Native / Expo tag presetbash
adb logcat -v time ReactNative:V ReactNativeJS:V ReactNativeJNI:V Expo:V HermesVM:V AndroidRuntime:E *:Sshelladb logcat -v time ReactNative:V ReactNativeJS:V ReactNativeJNI:V Expo:V HermesVM:V AndroidRuntime:E *:S
💥Crashes & ANRs
# Crash ring buffer only
adb logcat -b crash -v time# Classic Java/Kotlin runtime crashes
adb logcat -v time AndroidRuntime:E *:S# ANR digests & details
adb logcat -v time ActivityManager:E *:S
adb shell dumpsys activity anr# Recent crash/ANR from DropBox store
adb shell dumpsys dropbox --print system_app_crash
adb shell dumpsys dropbox --print system_app_anr🔵Bluetooth (BLE) focus
Useful Android tags: BluetoothGatt, BluetoothLeScanner, bt_stack, bt_btm_ble, BtGatt.GattService
# Focus on BLE logs
adb logcat -v time BluetoothGatt:D BluetoothLeScanner:D bt_stack:D bt_btm_ble:D BtGatt.GattService:D *:S# Combine with your app PID (less noise)
PID=$(adb shell pidof -s com.yourcompany.yourapp)
adb logcat --pid=$PID -v time BluetoothGatt:D bt_stack:D bt_btm_ble:D *:S🧪HCI snoop (packet‑level)
- 1Enable snoop logging on device
Developer options →
Enable Bluetooth HCI snoop log. - 2Reproduce and pull the logbash
adb shell ls /sdcard | grep -i btsnoop adb pull /sdcard/btsnoop_hci.log . # Some devices: adb pull /data/misc/bluetooth/logs/btsnoop_hci.log . - 3Analyze
Open
btsnoop_hci.login Wireshark (Decode As → Bluetooth HCI).
📜JavaScript / Hermes signals
# Bash: grep for common JS/Hermes errors
adb logcat -v time | grep -Ei "(Hermes|ReactNativeJS|Unhandled promise|TypeError|Invariant Violation)"# PowerShell: Select-String equivalent
adb logcat -v time | Select-String -Pattern "Hermes|ReactNativeJS|Unhandled promise|TypeError|Invariant Violation"💾Save sessions to a file
# Bash with timestamps
a db logcat -v time | tee "$(date +%F_%H-%M-%S)_logcat.txt"# PowerShell with timestamps
adb logcat -v time | Tee-Object -FilePath "$(Get-Date -Format 'yyyy-MM-dd_HH-mm-ss')_logcat.txt"# App-only to file (Bash)
PID=$(adb shell pidof -s com.yourcompany.yourapp)
adb logcat --pid=$PID -v time | tee "$(date +%F_%H-%M-%S)_yourapp_pid_$PID.txt"# App-only to file (PowerShell)
$pid = adb shell pidof -s com.yourcompany.yourapp
adb logcat --pid=$pid -v time | Tee-Object -FilePath "$(Get-Date -Format 'yyyy-MM-dd_HH-mm-ss')_yourapp_pid_$pid.txt"🧰Handy one‑liners
# Clean start + app-only + timestamps
adb logcat -c && PID=$(adb shell pidof -s com.yourcompany.yourapp) && adb logcat --pid=$PID -v time# Crash-only
adb logcat -v time -b crash# BLE preset
adb logcat -v time bt_stack:D bt_btm_ble:D BluetoothGatt:D BluetoothLeScanner:D *:S# RN/Expo verbose
adb logcat -v time ReactNative:V ReactNativeJS:V ReactNativeJNI:V Expo:V HermesVM:V AndroidRuntime:E *:S🧠Memory & native crashes
# Memory snapshot for your app
PID=$(adb shell pidof -s com.yourcompany.yourapp)
adb shell dumpsys meminfo $PID# Tombstones (native crashes)
adb shell ls -ltr /data/tombstones
# Pull latest (if device allows root)
adb root
adb pull /data/tombstones/tombstone_XX# Everything bagel (large zip)
adb bugreport bugreport-$(date +%F_%H-%M-%S).zipadb bugreport bugreport-$(Get-Date -Format 'yyyy-MM-dd_HH-mm-ss').zip🧩Shell helpers (drop-in)
Bash
# Logcat for given package (auto-PID)
alogpkg() {
local PKG="$1"; adb logcat -c; local PID=$(adb shell pidof -s "$PKG");
if [ -z "$PID" ]; then echo "No PID for $PKG (is the app running?)"; return 1; fi
echo "PID=$PID"; adb logcat --pid=$PID -v time;
}
# RN/Expo tags preset
alogrn() {
adb logcat -v time ReactNative:V ReactNativeJS:V ReactNativeJNI:V Expo:V HermesVM:V AndroidRuntime:E *:S
}
# BLE preset
aloble() {
adb logcat -v time bt_stack:D bt_btm_ble:D BluetoothGatt:D BluetoothLeScanner:D *:S
}PowerShell
function ALogPkg {
param([string]$Package)
adb logcat -c | Out-Null
$pid = adb shell pidof -s $Package
if (-not $pid) { Write-Host "No PID for $Package (is the app running?)"; return }
Write-Host "PID=$pid"
adb logcat --pid=$pid -v time
}
function ALogRN {
adb logcat -v time ReactNative:V ReactNativeJS:V ReactNativeJNI:V Expo:V HermesVM:V AndroidRuntime:E *:S
}
function ALoBLE {
adb logcat -v time bt_stack:D bt_btm_ble:D BluetoothGatt:D BluetoothLeScanner:D *:S
}🧭Troubleshooting flows
- App suddenly closes:
adb logcat -c→adb logcat -b crash -v time(terminal A), andadb logcat --pid=$(adb shell pidof -s com.yourcompany.yourapp) -v time(terminal B). Reproduce; inspectAndroidRuntime/libcfatals. - BLE connects/writes flaky: Use BLE preset; verify connection → services discovered → characteristics steps; if needed, enable HCI snoop and analyze in Wireshark.
- ANR:
adb shell dumpsys activity anr; watchActivityManagerfor blocked main thread stacks.
📝Notes & gotchas
- Android 12+ foreground service rules can kill BLE if not using proper permissions/notifications.
- Native crashes bypass Metro — rely on
-b crashand tombstones. - Vendor tags can differ; start wide, then refine filters.
- Package names differ between Expo Go and Dev Builds; PID filters depend on the actual running package.
Filed under: React Native, Expo, Android, adb, Bluetooth, Troubleshooting, Crash / ANR