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 devices
showsdevice
). - 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 yourapp
shell# 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.yourapp
shelladb 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 time
shell$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 *:S
shelladb 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.log
in 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).zip
adb 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
/libc
fatals. - 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
; watchActivityManager
for 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 crash
and 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