Knowledge Base
Mobile Development
2025-10-03
8 min

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.

React Native
Expo
Android
adb
Bluetooth
Crash/ANR
Troubleshooting

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 shows device).
  • Know your package name (Expo Go vs Dev Build differ).

Quick checks

  1. 1
    List packages and find yours
    bash
    # 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
  2. 2
    Get your app PID (used for tight filters)
    bash
    adb shell pidof -s com.yourcompany.yourapp
    shell
    adb shell pidof -s com.yourcompany.yourapp
ℹ️
For Expo Dev Builds your package is usually com.company.app. Classic Expo Go uses host.exp.exponent.

🌊See everything (raw firehose)

bash
adb logcat -v time
bash
# Clear old logs first
adb logcat -c

🎯App‑scoped logging (PID & TAG filters)

  1. 1
    Filter 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
  2. 2
    React Native / Expo tag preset
    bash
    adb logcat -v time   ReactNative:V ReactNativeJS:V ReactNativeJNI:V Expo:V HermesVM:V AndroidRuntime:E *:S
    shell
    adb logcat -v time ReactNative:V ReactNativeJS:V ReactNativeJNI:V Expo:V HermesVM:V AndroidRuntime:E *:S

💥Crashes & ANRs

bash
# Crash ring buffer only
adb logcat -b crash -v time
bash
# Classic Java/Kotlin runtime crashes
adb logcat -v time AndroidRuntime:E *:S
bash
# ANR digests & details
adb logcat -v time ActivityManager:E *:S
adb shell dumpsys activity anr
bash
# 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

bash
# Focus on BLE logs
adb logcat -v time   BluetoothGatt:D BluetoothLeScanner:D bt_stack:D bt_btm_ble:D BtGatt.GattService:D *:S
bash
# 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)

  1. 1
    Enable snoop logging on device

    Developer options → Enable Bluetooth HCI snoop log.

  2. 2
    Reproduce and pull the log
    bash
    adb shell ls /sdcard | grep -i btsnoop
    adb pull /sdcard/btsnoop_hci.log .
    # Some devices:
    adb pull /data/misc/bluetooth/logs/btsnoop_hci.log .
  3. 3
    Analyze

    Open btsnoop_hci.log in Wireshark (Decode As → Bluetooth HCI).

📜JavaScript / Hermes signals

bash
# Bash: grep for common JS/Hermes errors
adb logcat -v time | grep -Ei "(Hermes|ReactNativeJS|Unhandled promise|TypeError|Invariant Violation)"
shell
# PowerShell: Select-String equivalent
adb logcat -v time | Select-String -Pattern "Hermes|ReactNativeJS|Unhandled promise|TypeError|Invariant Violation"
ℹ️
Ensure source maps are enabled in development for actionable stack traces.

💾Save sessions to a file

bash
# Bash with timestamps
a db logcat -v time | tee "$(date +%F_%H-%M-%S)_logcat.txt"
shell
# PowerShell with timestamps
adb logcat -v time | Tee-Object -FilePath "$(Get-Date -Format 'yyyy-MM-dd_HH-mm-ss')_logcat.txt"
bash
# 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"
shell
# 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

bash
# Clean start + app-only + timestamps
adb logcat -c && PID=$(adb shell pidof -s com.yourcompany.yourapp) && adb logcat --pid=$PID -v time
bash
# Crash-only
adb logcat -v time -b crash
bash
# BLE preset
adb logcat -v time bt_stack:D bt_btm_ble:D BluetoothGatt:D BluetoothLeScanner:D *:S
bash
# RN/Expo verbose
adb logcat -v time ReactNative:V ReactNativeJS:V ReactNativeJNI:V Expo:V HermesVM:V AndroidRuntime:E *:S

🧠Memory & native crashes

bash
# Memory snapshot for your app
PID=$(adb shell pidof -s com.yourcompany.yourapp)
adb shell dumpsys meminfo $PID
bash
# Tombstones (native crashes)
adb shell ls -ltr /data/tombstones
# Pull latest (if device allows root)
adb root
adb pull /data/tombstones/tombstone_XX
bash
# Everything bagel (large zip)
adb bugreport bugreport-$(date +%F_%H-%M-%S).zip
shell
adb bugreport bugreport-$(Get-Date -Format 'yyyy-MM-dd_HH-mm-ss').zip

🧩Shell helpers (drop-in)

Bash

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

shell
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 -cadb 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; watch ActivityManager 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

Last updated: 2025-10-03