CLOSE
ADB

ADB

Updated on 19 Oct, 2026 49 mins read 58 views

ADB is one of the most useful tools for understanding what is happening inside an Android device. It lets us communicate with a phone from your computer, inspect running processes, install apps, read logs, explore files, debug applications, and investigate parts of Android's operating system.

ADB has its own commands, while adb shell gives you access to a separate set of commands provided by Android's shell environment.

What is ADB?

ADB stands for Android Debug Bridge. It is a command-line tool included in Google's Android SDK Platform-Tools. It allows your computer to communicate with an Android device or emulator.

For example, you can run these commands from a computer terminal:

adb devices
adb install app.apk
adb logcat
adb shell

ADB Commands versus shell commands

There are two different command environments.

Environment A –  Your computer's terminal
Commands start with `adb`.
These are ADB client commands executed on your computer.
Environment B - Android's shell
Commands execute on the device.
After the shell opens:
These are commands available inside Android's shell environment.

You don't need to enter the interactive shell for every command.

Set up ADB and connect your phone

Step 1: Install Platform-Tools

Download from the Google's official page. The package contains adb and is available separately from the full Android Studio installation.

Open a terminal in the directory containing the executable, or add that directory to your system's PATH.

Check that ADB works:

Step 2: Enable USB debugging

On your Android phone:

  1. Open Settings and find About phone.
  2. Tap Build number repeatedly, commonly seven times, to enable Developer options.
  3. Open Developer options and enable USB Debugging.
  4. Connect the phone to the computer using USB.
  5. Unlock your phone and approve the debugging authorization prompt, checking the computer's identity before trusting it.

Menu names can vary by manufacturer.

Step 3: Verify the connection

For more details:

Example:

The status matters:

Status

Meaning

device

ADB has an active connection.

unauthorized

The phone has not authorized this computer.

offline

ADB cannot currently communicate properly with the device.

No device listed

No device was discovered by the ADB server.

A device status means the ADB connection is established; it doesn't guarantee that Android has completely finished booting.

Connection and Device Management

These commands manage the server, find devices, and target the right one. They are the first things you run every session.

Seeing devices & the server:

CommandWhat it does
adb devicesList connected devices and their state (device, unauthorized, offline)
adb devices -lSame, with more detail (model, transport id, usb path
adb start-serverStart the background server explicitly (usually automatic)
adb kill-serverStop the server – the universal first fix for weird states
adb reconnectReset the connection to a device
adb reconnect offlineReset only devices stuck in offline
adb get-statePrint one device's state
adb get-serialnoPrint the device's serial number

Targeting a specific device (when more than one is connected, or over network):

2 File Transfer & app install

Moving files – push and pull. These copy between laptop and device:

adb push localfile.txt /sdcard/  # laptop -> device
adb push ./myfolder /sdcard/myfolder # a whole directory
adb pull /sdcard/photo.jpg .  # device -> laptop (to current dir)
adb pull /sdcard/DCIM ./backup # pull a directory

Installing apps – adb install. This pushes an APK and runs PackageManager's install:

adb install app.apk                            # install
adb install -r app.apk                         # reinstall, keeping data (-r = replace)
adb install -d app.apk                          # allow version downgrade
adb install -g app.apk                          # grant all runtime permissions at install
adb install -t app.apk                          # allow a 'test' APK (debug-built)
adb install -i com.android.vending app.apk      # set the installer package name
adb install-multiple base.apk split_config.arm64_v8a.apk split_config.en.apk
adb install-multiple -r *.apk                   # all splits, reinstall

There's also install-multi-package for installing several different apps automatically in one transaction.

Uninstalling:

adb uninstall com.example.app                   # remove app + its data
adb uninstall -k com.example.app                # -k = keep the data/cache directories

The install flow, under the hood. adb install really does: push the APK to a staging area on the device, then invoke pm install (PackageManagerService), which verifies the signature, parses the manifest, assigns the app a UID, sets up its data dir, and registers its components/permissions. You can do the two steps by hand — adb push app.apk /data/local/tmp/ then adb shell pm install /data/local/tmp/app.apk — which is sometimes needed for edge cases, and shows that install is just a convenience wrapper over pm.
Related install/package host commands:

CommandWhat it does
adb shell pm path <pkg>Find where an installed APK lives (to pull it)
adb pull $(adb shell pm path <pkg> | sed ‘s/package://’)One-liner to pull an installed app's base APK
adb shell pm clear <pkgadb>Wipe an app's data to factory-fresh (keeps the app)
adb shell pm list packagesList installed packages

A common recipe – extract an installed app:

adb shell pm path com.example.app              # e.g. prints: package:/data/app/.../base.apk
adb pull /data/app/.../base.apk .               # copy it to the laptop

3 Logging, debugging & bug capture

adb logcat the live system log, your single most-used diagnostic. Everything the OS and apps log streams here.

Core usage:

adb logcat                        # live stream (Ctrl-C to stop)
adb logcat -d                     # dump the current buffer and exit (no streaming)
adb logcat -c                     # CLEAR the buffer (run before a test)
adb logcat -t 100                 # show the last 100 lines and exit
adb logcat -t '01-01 10:00:00.000'   # show lines since a time
adb logcat > log.txt              # save to a file on the laptop

The reset-reproduce-read loop is the professional workflow: adb logcat -c (clear) -> do one action on the device -> adb logcat -d (read only what that action produced). Without clearing first you drown in backlog.

Output formats (-v) change how each line looks:

-v formatShows
briefdefault-ish: priority/tag/pid + message
timeadds a timestamp
threadtimetimestamp + PID + TID (the most useful; often the default now)
colorcolorizes by priority
longeach field on its own lines (verbose)

Combine: adb logcat -v threadtime -v color.

Filtering by tag and priority: The syntax is TAG:PRIORITY pairs ending with *:S (silence the rest). Priorities: Verbose < Debug < Info < Warn < Error < Fatal.

adb logcat *:E                    # errors and worse only
adb logcat ActivityManager:I *:S  # only ActivityManager at Info and above
adb logcat -s ActivityManager     # -s is shorthand for a single-tag filter
adb logcat -e "token|password"    # -e = only lines matching this regex

Filtering by process:

adb logcat --pid=$(adb shell pidof -s com.example.app)   # one app's logs only

Buffers (-b) – logcat reads several separate ring buffers:

BufferContents
mainapp logs (default)
systemframework/system logs
crashcrash logs only – adb logcat -b crash for just fatals
eventsstructured system events (am_proc_start, launch times)
radiotelephony/modem
allevery buffer

Example: adb logcat -b crash -d grabs the latest crash stack; adb logcat -b events shows the Activity Manager's structured record of what it did.

4 Running commands & lifecycle control

adb shell – two modes. This is how you run commands on the device:

adb shell  # INTERACTIVE: drops into a device shell prompt ($)
adb shell ls /sdcard  # ONE-SHOT: runs one command and returns immediately

Interactive mode is for exploring (you type command after command, exit to leave). One-shot mode is for scripting and quick checks. It's the form you will use in the most examples and in scripts.

Getting root in the shell. On your Magisk-rooted retails device:

adb shell  # prompt is $ (shell user, uid 2000)
su  # prompt becomes # (root) - Magisk may prompt to grant
# .... root commands
exit  # drop root
exit  # leave the shell

Or run a single root command from the laptop without going interactive:

adb shell su -c 'ls /data/data'    # run one command as root, come straight back

The quoting trap – the #1 source of confusion. When you run adb shell ‘something’, there are two shells involved: your laptop's shell and the device's shell. Both try to interpret quotes, $, *, >, ;, etc. Rules of thumb:

  • Wrap the whole remote comand in single quotes so your laptop shell passes it through untouched: adb shell ‘echo $RANDOM’ – the $RANDOM is expanded on the device, not your laptop.
  • A redirect like adb shell ‘ps > /sdcard/ps.txt’ (quoted) writes the file on the device; unquoted adb shell ps >ps.txt writes it on the laptop. The quotes decide where the redirect happens.
  • Globs (*) similarly: quoted = expanded on device, unquoted = expanded on laptop (usually wrong).
  • When in doubt, single-quote the entire remote command and reason about “this runs on the device”.

Forwarding ports (handy for debugging device-side servers, or Frida):

adb forward tcp:8080 tcp:8080     # laptop:8080 -> device:8080
adb reverse tcp:3000 tcp:3000     # device:3000 -> laptop:3000 (device reaches your laptop)
adb forward --list                 # list active forwards
adb forward --remove-all           # clear them

adb reverse is especially useful: it lets an app on the device reach a server running on your laptop – common in development and instrumentation.

5 The on-device shell toolbox (Linux side)

Once inside adb shell, you are in a Linux-like environment. Most standard Unix commands exist, but provided by toybox (a compact single-binary implementation), not the GNU coreutils you know from desktop Linux. That means flags are a subset – some option you expect are missing. When one isn't recognized, check toybox or <command> --help.

Navigation & file operations:

CommandUse
ls / ls -l / ls -la / ls -Z

List files: -l = long

-a = hidden

- Z = SELinux context

cd / pwdChange / print working directory
cat / head / tailPrint file / first lines / last lines (tail -f to follow)
cp / mv / rm / mkdir / rmdirCopy / move / remove / make dir
find <path> -name ‘*.db’Search for files
stat <file>Detailed file metadata (size, perms, times, inode)
file <file>Identify a file's type (if present)
ln -s target linkSymlink
touchCreate/update a file timestamp

Text processing (greate for carving signal out of dumpsys / logcat):

CommandUse
grep / grep -i / grep -E / grep -R

Search text; -i = ignore case,

-E = regex,

-R = recursive

sed ‘s/a/b/’Stream edit (substitute)
awk ‘{print $2}’Field extraction ($2 = 2nd column)
cut -d: -f1Cut by delimiter
sort / uniq / wc -lSort / dedupe / count lines
tr / xargsTranslate chars / build commands from input

System & process inspection:

CommandUse
ps -A / ps -A -o PID,USER,NAMEList processes; custom columns with -o
top / top -m 10 - n 1Live resource use; -n 1 one snapshot
kill <pid> / kill -9 <pid>Terminate a process (root for other's processes)
pidof <pkg>Get a process's PID by name
id / whoamiCurrent UID/GID / username
uname -aKernel version/arch
uptime / dateUptime / current time
dmesgKernel ring buffer (root; where avc: SELinux denials appear)
getevent / sendeventRead / inject raw input events (low-level)

Storage & memory:

CommandUse
df -hFree space per file system
du -sh <dir>Size of a directory
mountLists mounts + flags (see ro/rw)
free -hRAM usage (if present)
cat / proc/meminfoDetailed memory info
lsofOpen files (if present; else ls -l /proc/<pid>/fd)

Permissions & ownership (mostly root-only to change):

CommandUse
chmod 644 <file>Change permission bits
chown user:group <file>Change owner
ls -Z / chconView / change SELinuz context (root)

Networking:

CommandUse
ip addr / ip routeInterfaces & routing (replaces ifconfig)
netstat -tunp / ss -tunpActive sockets + owning process (root shows PID)
ping <host>Connectivity test
cat /proc/net/…Raw network tables

What's different from desktop Linux.

6 Android-specific shell commands

These are the commands that make it Android, not just Linux – front-ends to the framework services. They have no desktop equivalent and are where most of your real work happens. (All run inside adb shell, or via adb shell <cmd> from the laptop.)

pm – Package Manager (talks to PackageManagerService):

CommandUse
pm list packagesList all packages
pm list packages -3 / -sThird-party only / system only
pm list packages -f Show the APK path with each package
pm path <pkg>Print an installed app's APK path(s)
pm install / pm uninstall <pkg>Install / uninstall (what adb install wraps)
pm clear <pkg>Wipe an app's data to factory-fresh
pm grant <pkg> <perm> / pm revoke …Grant / revoke a runtime permission
pm list permissions -d -gList dangerous permission, grouped
pm disable-user <pkg> / pm enable <pkg>Disable / re-enable an app
pm dump <pkg>Everything PMS knows (like dumpsys package <pkg>)

am –  Activity Manager (talks to ActivityManagerService):

CommandUse
am start -n <pkg>/<activity>Launch a specific activity (explicit intent)
am start -a <ACTION> -d <uri>Fire an implicit intent (e.g., open a URL)
am start … --es key valAdd a string extra (--ez bool, --ei int, --el long)
am startservice / am start-foreground-serviceStart a service
am broadcast -a <ACTION>Send a broadcast
am force-stop <pkg>Kill an app completely
am kill <pkg>Kill background processes of an app
am instrumentRun instrumentation/tests

settings – read/write the system settings database:

settings lists global   # all global settings
settings get system screen_brightness
settings put global http_proxy 192.168.1.50.8080  # set a system-wide proxy
settings put global http_proxy :0     # clear it
settings delete secure <key>

getprop/setprop – system properties

getprop     # dump ALL properties
getprop ro.build.version.sdk   # read one (ro.* = read-only, set at boot)
setprop debug.myflag 1   # set a writable property (root for most)
watch -n1 getprop sys.boot_completed   # watch a property change

 

Buy Me A Coffee

Leave a comment

Your experience on this site will be improved by allowing cookies Cookie Policy