Skip to content
Bugwise
Menu
Mobile Testing

adb Basics

Use Android Debug Bridge to install builds, reset apps, read logcat, capture crash stack traces, open deep links and fake device conditions, all from your terminal.

25 min intermediate Mobile

A tester on a shopping app filed this bug: “App sometimes crashes when opening links.” The developer tried a few links, nothing crashed, and the ticket came back marked Cannot reproduce. Two weeks later a marketing newsletter went out to 400,000 people, and the app crashed for every single one who tapped the sale link.

A second tester picked the ticket up. Ten minutes later they had the exact link, a one-line command that crashed the app every time, the device and app version, and four lines of log ending in DeepLinkParser.kt:27. The fix took twenty minutes.

The difference wasn’t luck. The second tester used adb.

Why it matters

adbadbAndroid Debug Bridge: a command-line tool for installing apps, reading logs and controlling Android devices.Open in glossary → (Android Debug Bridge) is the command-line tool that lets your computer talk to an Android phone, tablet or emulatorEmulatorSoftware that imitates a real device's hardware and OS on your computer, like the Android Emulator.Open in glossary →. For a manual tester it’s a superpower:

You don’t need to be a developer. You need about fifteen commands, and you’ll learn them on this page.

What is adb?

adb has three parts. You only ever type the first one:

Your computer

adb client: the adb command you type in the terminal

adb server: runs in the background (port 5037) and keeps track of connected devices

USB or Wi-Fi

Phone or emulator

adbd: a small service on the device that runs your commands

adb shell … runs a command on the device, for example pm, am, input, dumpsys

A useful mental model: commands like adb install and adb logcat are adb features. Commands after adb shell are Android’s own tools, running on the phone: pm (package manager), am (activity manager), input, settings, dumpsys.

Setting it up

  1. Install the platform tools. adb is part of Android’s SDK Platform-Tools. If you have Android Studio, it’s already installed in the SDK folder’s platform-tools directory (paths below). Without Android Studio, download SDK Platform-Tools from developer.android.com, or on a Mac run brew install --cask android-platform-tools.
  2. Add it to your PATH, so adb works in any folder. On macOS with zsh, add the export line below to ~/.zshrc and open a new terminal. Check with adb version.
  3. Turn on Developer options on the phone. Go to Settings › About phone and tap Build number seven times until it says “You are now a developer”. On Samsung it’s under About phone › Software information.
  4. Turn on USB debugging. Open Settings › System › Developer options (on Samsung, Developer options appear at the bottom of Settings) and switch on USB debugging.
  5. Connect and allow. Plug in a USB cable. The phone asks “Allow USB debugging?” and shows your computer’s key fingerprint. Tick Always allow from this computer and tap Allow.
  6. Check the connection. Run adb devices. Emulators started from Android Studio show up automatically, no setup needed.
# Where Android Studio puts adb
# macOS:   ~/Library/Android/sdk/platform-tools
# Windows: %LOCALAPPDATA%\Android\Sdk\platform-tools
# Linux:   ~/Android/Sdk/platform-tools

# macOS (zsh): add this line to ~/.zshrc
export PATH="$PATH:$HOME/Library/Android/sdk/platform-tools"
$ adb devices
List of devices attached
38121FDJH00ABC	device
emulator-5554	device
State in adb devicesMeaningWhat to do
deviceConnected and readyStart testing
unauthorizedThe phone hasn’t accepted this computer yetUnlock the phone and tap Allow on the prompt. No prompt? Developer options › Revoke USB debugging authorizations, then reconnect
offlineConnected but not respondingReconnect the cable, or run adb kill-server and then adb devices
(nothing listed)adb can’t see the phoneTry another cable (some only charge), check USB debugging is on, set USB mode to file transfer

The commands testers use most

Throughout this lesson the example app is ShopEasy, package name com.shopeasy.app. Every Android app has a unique package name like this; find yours with adb shell pm list packages | grep shop.

Install, update, reset

adb install shopeasy.apk                  # install an APK
adb install -r shopeasy.apk               # reinstall/update and keep app data
adb uninstall com.shopeasy.app            # remove the app and its data
adb shell pm clear com.shopeasy.app       # wipe app data: like a fresh install, without reinstalling

-r means “replace the existing app”. Recent Android versions replace by default, but -r makes your intent clear and is what you’ll see in most guides. Installing a new version over an old one with its data intact is exactly what users experience from the Play Store, so it’s the heart of upgrade testingUpgrade testingChecking that updating from an older app version keeps the user's data and settings working.Open in glossary →.

pm clear is the tester’s reset button: it signs the user out, clears caches and settings, and shows onboarding again. Use it before every “first launch” test.

ErrorWhat it means
INSTALL_FAILED_VERSION_DOWNGRADEYou’re installing an older version over a newer one. Uninstall first (or use -d on debuggable builds)
INSTALL_FAILED_UPDATE_INCOMPATIBLEThe installed app was signed with a different key (e.g. a Play Store build vs a debug build). Uninstall first
INSTALL_FAILED_INSUFFICIENT_STORAGEThe device is full

Read the logs with logcat

Android writes everything that happens into a system log. adb logcat streams it to your terminal until you press Ctrl+C. It’s a lot, so you’ll almost always filter it.

A logcat line looks like this:

10-13 14:02:11.482  4821  4821 E AndroidRuntime: FATAL EXCEPTION: main
└─ date & time ──┘  PID   TID  │ └── tag ─────┘  └── message ──────────┘
                               └ level
LevelNameUse
V / DVerbose / DebugDeveloper detail, usually noise for testers
IInfoNormal events: activity started, request finished
WWarningSomething odd but not fatal
EErrorSomething failed. Crashes are logged here
FFatalNative crashes and fatal system problems
adb logcat -c                                              # clear the log before you reproduce a bug
adb logcat '*:E'                                           # only errors and worse, from all tags
adb logcat --pid=$(adb shell pidof -s com.shopeasy.app)    # only the running app's lines
adb logcat | grep -i shopeasy                              # lines that mention the app
adb logcat -b crash                                        # only the crash buffer
adb logcat -d > log.txt                                    # dump the current log to a file and stop

Find a crash stack trace

When an Android app crashes, it writes a block that starts with FATAL EXCEPTION. Find it like this:

adb logcat -c
# ...reproduce the crash on the phone...
adb logcat -d | grep -A 20 "FATAL EXCEPTION"

Here’s how to read the result:

E AndroidRuntime: FATAL EXCEPTION: main                       ← a crash happened on the main thread
E AndroidRuntime: Process: com.shopeasy.app, PID: 4821        ← which app
E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ...  ← wrapper
E AndroidRuntime:     at android.app.ActivityThread...       ← framework code (skip)
E AndroidRuntime: Caused by: java.lang.NumberFormatException: For input string: "summer-sale"   ← root cause
E AndroidRuntime:     at java.lang.Integer.parseInt(Integer.java:747)                  ← Java's code
E AndroidRuntime:     at com.shopeasy.app.product.DeepLinkParser.productId(DeepLinkParser.kt:27)  ← the app's code!
  1. Find FATAL EXCEPTION. It marks the start of the crash.
  2. Jump to the last Caused by:. That’s the root cause: the exception type and its message.
  3. Find the first line below it from the app’s own package (com.shopeasy.app…). That file and line number is where developers will start.
  4. Copy from FATAL EXCEPTION through that line into the bug report. Attach the full log as a file if needed.

Screenshots and screen recordings

adb exec-out screencap -p > screen.png         # screenshot straight to your computer
adb shell screenrecord /sdcard/bug.mp4         # record; press Ctrl+C to stop (max 3 minutes)
adb pull /sdcard/bug.mp4                       # copy the video to your computer

exec-out sends the raw image bytes back unchanged, so redirecting them with > gives you a valid PNG. screenrecord records video without sound.

adb shell am start -a android.intent.action.VIEW -d "shopeasy://product/42"
adb shell am start -a android.intent.action.VIEW -d "https://shop.example.com/product/42" com.shopeasy.app

am start asks Android to open a link, exactly as if the user had tapped it in an email. Adding the package name at the end forces it to open in that app. This is the fastest way to test deep links, including the nasty ones: unknown IDs, missing parameters, letters where numbers are expected.

Type and press keys

adb shell input text "running%sshoes"     # types "running shoes" into the focused field (%s = space)
adb shell input keyevent KEYCODE_ENTER    # also KEYCODE_BACK, KEYCODE_HOME (or 66, 4, 3)
adb shell am force-stop com.shopeasy.app  # kill the app, e.g. to test a cold start

input text is great for long or tricky test dataTest dataThe input values, accounts and records you use while testing.Open in glossary →: a 200-character name, an email with a plus sign, a coupon code you need to type twenty times.

Fake device conditions

adb shell dumpsys battery unplug                     # pretend the charger is unplugged
adb shell dumpsys battery set level 5                # pretend the battery is at 5%
adb shell dumpsys battery reset                      # back to the real battery state

adb shell settings put system font_scale 1.3         # bigger text (1.0 is the default)
adb shell settings put system font_scale 1.0         # back to normal

adb shell cmd uimode night yes                       # dark theme on (no = off)

font_scale mimics the user’s font size setting. Android 14 and newer allow up to 2.0 (200%), and the large sizes are where truncationTruncationText that gets cut off because it doesn't fit its space.Open in glossary → bugs live. It changes the setting for the whole phone, so set it back afterwards.

Try it: the adb playground

Time to type. The terminal below is fake, so nothing can break, but the commands and outputs follow real adb. Try installing, clearing data, opening a deep link, faking 5% battery, bumping the font size, and reading logcat. Then try shopeasy://product/summer-sale instead of 42, and look at logcat again.

adb playground

A safe fake terminal. Every command changes the phone on the right.

Terminal — zsh
# A Pixel 8 is plugged in over USB with USB debugging on.
# Type a command, or click one in the cheat sheet. Try: adb devices
~ $

Tip: ↑ / ↓ recall earlier commands. Type clear to empty the screen.

14:0285%⚡

Hi, Ana

2
Search products

Popular this week

Cheat sheet · click to paste into the terminal

Devices

Install & reset

Open & control

Logs

Evidence

Device conditions

Wireless & network

Wireless debugging

No cable? Since Android 11 you can use adb over Wi-Fi. The phone and computer must be on the same network.

  1. On the phone, open Developer options › Wireless debugging and switch it on.
  2. Tap Pair device with pairing code. The phone shows an IP address with a port and a six-digit code.
  3. On your computer run adb pair 192.168.1.23:37199 (use the address shown) and enter the code.
  4. Recent adb versions often connect automatically after pairing. If not, go back to the Wireless debugging screen and note the IP address & Port. It’s a different port from the pairing one. Run adb connect 192.168.1.23:41235.
  5. Check with adb devices. The phone now appears with its IP address.

Android Studio can do the same with a QR code: Device Manager › Pair Devices Using Wi-Fi. On Android 10 and older, connect once by USB, run adb tcpip 5555, unplug, then adb connect <phone-ip>:5555.

What to test with adb

Fresh state and upgrades

  • First launch: pm clear, then open the app. Onboarding, permission prompts and empty states should all appear.
  • Upgrade: install the old version, create data (log in, fill the cart), then adb install -r the new version. Nothing should be lost.
  • Reinstall: uninstall then install. The app must not crash on missing data.

Entry points

  • Deep links with valid, unknown, deleted and malformed IDs, missing parameters, and while logged out.
  • Cold start vs warm start: am force-stop, then open the deep link.

Device conditions

  • Low battery (5%, unplugged): does the app reduce background work? Does it still function?
  • Large fonts (1.3, 1.5, 2.0): no clipped buttons, no text running off the screen.
  • Dark theme switched while the app is open.

Evidence

  • Clear logcat, reproduce, and save the crash block for every crash or freeze.
  • Record a video of anything that’s hard to describe.

Bugs adb helps you find

#BugWhat you seeTypical severity
1Crash on unexpected deep link inputLetters, an unknown ID or a missing parameter in a link closes the appHigh
2Crash on first launch after clearing dataApp assumes a saved token exists; after pm clear it crashes instead of showing loginHigh
3Data lost on upgradeAfter install -r the user is logged out or the cart is emptyHigh
4Layout breaks at large font scaleAt font_scale 1.3 buttons are clipped or the Pay button moves off-screenMedium
5No low-battery handlingAt 5% the app keeps heavy background syncing or video autoplayLow–Medium
6Hidden errorsNo visible problem, but logcat shows repeated E lines, e.g. failing API calls on every screenMedium
7Deep link ignores login stateA link opens an account page without asking the logged-out user to sign inHigh

Practice: investigate the crash

A real support ticket just came in. Use the terminal to reproduce the crash, find the FATAL EXCEPTION, click the exact cause line, and decide what evidence goes into the bug report.

Investigate the crash

Reproduce it, read the log, and build the evidence for a bug report.

0/4

Support ticket SUP-2291

"I tapped the Summer Sale link in your newsletter and the app closed. Tried 3 times." The newsletter link is shopeasy://product/summer-sale.

  1. 1. Reproduce the crash
  2. 2. Find the FATAL EXCEPTION
  3. 3. Pinpoint the cause line
  4. 4. Assemble the evidence

Step 1 · Reproduce the crash

Clear the old log first, so the crash is easy to find. Then open the newsletter link on the phone. Click a command to paste it, then press Enter.

Terminal — zsh
# Pixel 8 connected over USB. ShopEasy 2.4.1 is open on the home screen.
~ $
14:0285%⚡

Hi, Ana

2
Search products

Popular this week

Example test cases

TC-ADB-001First launch after clearing app data shows onboarding

Preconditions

  • ShopEasy installed, user logged in
  • Device connected, adb devices shows "device"

Steps

  1. Run adb shell pm clear com.shopeasy.app
  2. Open ShopEasy from the launcher

Expected result

The onboarding screen with Log in / Create account is shown. No crash, no previous user data.

TC-ADB-002Upgrade keeps the session and cart

Preconditions

  • ShopEasy 2.3.0 installed
  • User logged in with 2 items in the cart

Steps

  1. Run adb install -r shopeasy-2.4.1.apk
  2. Open ShopEasy

Expected result

The user is still logged in and the cart shows the same 2 items.

TC-ADB-003Product deep link opens the product page

Steps

  1. Run adb shell am start -a android.intent.action.VIEW -d "shopeasy://product/42"

Expected result

ShopEasy opens on the "Trail Runner X" product page.

TC-ADB-004Deep link with a non-numeric product ID is handled

Steps

  1. Run adb logcat -c
  2. Run adb shell am start -a android.intent.action.VIEW -d "shopeasy://product/summer-sale"
  3. Run adb logcat -d | grep "FATAL EXCEPTION"

Expected result

The app shows a friendly "Product not found" screen (or the sale page). No FATAL EXCEPTION in logcat.

TC-ADB-005Checkout is usable at 130% font scale

Steps

  1. Run adb shell settings put system font_scale 1.3
  2. Open the cart and go to checkout
  3. Scroll to the bottom

Test data

Reset afterwards: adb shell settings put system font_scale 1.0

Expected result

All labels are readable and the Pay button is fully visible and tappable.

TC-ADB-006Low battery reduces background work

Steps

  1. Run adb shell dumpsys battery unplug
  2. Run adb shell dumpsys battery set level 5
  3. Browse the home feed for 1 minute

Test data

Reset afterwards: adb shell dumpsys battery reset

Expected result

The app keeps working; image prefetching / autoplay is paused as specified.

Tip: click a test case to expand it.

Checklist

adb testing checklist

0 of 11 checked

Check your understanding

Quick quiz

0/5 answered · 0 correct

  1. 1.Which command resets an app to a fresh-install state without reinstalling it?

  2. 2.adb devices shows your phone as "unauthorized". What do you do?

  3. 3.In a crash stack trace, which line should you point developers to first?

  4. 4.You run adb logcat --pid=$(adb shell pidof -s com.shopeasy.app) after the app crashed and get an error. Why?

  5. 5.You set the battery to 5% with dumpsys but the app shows no low-battery behavior. What is the most likely reason?

Key takeaways

  • adb connects your computer to Android devices and emulators over USB or Wi-Fi. Set it up once: platform-tools, Developer options, USB debugging, allow the computer.
  • Install and reset fast: install, install -r, uninstall, shell pm clear.
  • logcat is your evidence: clear it, reproduce, filter with '*:E', --pid or grep, and find FATAL EXCEPTION, the last Caused by and the first line of app code.
  • Fake conditions: deep links with am start, typing with input, battery with dumpsys battery, text size with font_scale. Always reset afterwards.
  • Put the adb command and the stack trace excerpt in your bug report, and “cannot reproduce” becomes rare.

Finished this page?Nice work, this page is complete!

Mark it as done to track your progress. It's saved in this browser, no account needed.

Its review cards are now in Bites ⚡
Esc

Type to search the whole site.