tip

Android ADB Tricks for your shell to boost your productivity

If you are Android developer and working a lot with different phones, there's a high chance you have collected a set of different scripts which help you to speed up your productivity.

Here's an overview of different scripts I use on a daily basis. (The scripts should work on all unix systems. Sorry windows users.

Setup

If you use zsh you can add these bash functions in your ~/.zshrc file, so they will be automatically available from your terminal.

adbm

Most of the days I have to work with good amount of different Android devices, which I tend to have connected to my computer. Most adb commands executed are only meant for a particular device only though. To help with this I created adbm which uses a env variable to execute adb commands for the same device.

adbm() {
    if [[ ( ${CURRENT_ADB_DEVICE} == "" ) ]]; then
        echo "Please add `export CURRENT_ADB_DEVICE=\"deviceId\"` to your .bashrc or .zshrc"
        exit 0
    fi

    adb -s $CURRENT_ADB_DEVICE ${1} ${2} ${3} ${4}
}

Additionally I have set up quick "shortcuts" to enable different phones.

Pixel4XL() {
	export CURRENT_ADB_DEVICE="serial-from-pix-4"
}

OnePlusNord() {
	export CURRENT_ADB_DEVICE="serial-from-oneplus-nord"
}

adbclearempty

Remove all empty directories within a path on the phone.

adbclearempty() {
    adb shell "find ${1} -type d -empty -delete"
}
➜ adbclearempty "/sdcard/Pictures"
# remove all empty dirs from pictures

adbpull

Often I find myself wanting to pull the newest files from the phone. For this purpose I got adbpull which allows me to automatically find and pull these files.

adbpull() {
    pullX=${2}
    if [[ ( ${2} == "" ) ]]; then
        pullX=1
    fi

    newestfiles=$(adb shell ls -crt ${1}/ | tail -n ${pullX} )

    while read -r line; do
        adb pull "${1}/${line}" "${line}"	
    done <<< "$newestfiles"
}
➜ adbpull "/sdcard/Pictures" "5"
# pull the newest 5 files from pictures

adbpulls

Similar to pulling the latest files from within a directory, it's also possible to pull all screenshots from today from the phone

adbpulls() {
    today=$(date +%Y%m%d)
    todaysscreenshots=$(adb shell 'ls /sdcard/Pictures/Screenshots/*'"${today}"'*' )
    for path in ${todaysscreenshots}; do
        name=$(basename "$path")
        if [ ! -f "$name" ]; then
            adb pull "$path"
        fi
    done
}

This is based on the awesome gist by Rebecca Franks, patched to work with zsh.

adbcurrent

One of the more tedious parts when working with all sorts of different apps and build variants can be to identify which package name a specific app features. Luckily there's a quick command which will output the package name from the current foreground app.

adbcurrent() {
    adb shell "dumpsys activity activities | grep mResumedActivity" | perl -pe 's/.+(com.+?)\/.*/$1/'
}
➜ adbcurrent
com.android.chrome
➜ adbcurrent
com.google.android.apps.messaging

adbcurrentls

If you ever found yourself wanting to list the external files of the current app, you may also find the next one very helpful.
(This one requires adbcurrent to be available too)

adbcurrentls() {
    currentpackagename=$(adbcurrent)
    adb shell run-as ${currentpackagename} ls ./${1}
}

adbcurrentpwd

Similar to only retrieve the actual external directory for the current launched (in foreground) app.

adbcurrentpwd() {
    currentpackagename=$(adbcurrent)
    adb shell run-as ${currentpackagename} pwd
}

adbcurrentpull

Pull a file from the app specific external directory if it is debuggable.

adbcurrentpull() {
    currentpackagename=$(adbcurrent)
    adb shell "run-as ${currentpackagename} cat ./${1}" > ${2}
}

adbuninstall

If you ever wanted to ensure all namespace related apps get uninstalled (including their test, dev, staging, ... variants). adbuninstall helped me many times. Usually I also have this set-up in the build if the goal is to ensure a clean fresh install.

adbuninstall() {
    if [[ ( ${1} == "" ) ]]; then
        echo "Please specify the filter on which package names to uninstasll"
    else
        uninstallApks=$(adb shell 'pm list packages -f | grep ' ${1} | sed -e 's/.*=//' | sed -e 's/^/adb uninstall /' | sort)

        while read -r line; do
            if [[ ( ${line} != "" ) ]]; then
                echo "Uninstalling: $line"
                eval $line || true
            fi
        done <<< "$uninstallApks"
    fi
}
➜ adbuninstall "com.mikepenz"

adbspeed

There's a wide variety of usb standards and cables with different speed. If you are left with installing large apps many times a day, you'd want to choose the fasted usb cable you can find. (some phones ship with slow cables)

adbspeed() {
    echo "Checking connected Android device USB Speeds"
    echo ""

    adb devices | while read line
    do
        if [ ! "$line" = "" ] && [ `echo $line | awk '{print $2}'` = "device" ]
        then
            device=`echo $line | awk '{print $1}'`
            
            system_profiler SPUSBDataType 2> /dev/null \
                | awk '
                    /Serial Number:/{p=$3}
                    /Speed:/{x=$4$5}
                    /Location ID:/{sub(/.*: /,""); printf("[%s] connected with speed up to: %s\n", p, x);}
                ' | while read line2
            do 
                if [[ ( ${line2} ==  "[${device}"* ) ]]; then
                    device_model=$(adb -s "${device}" shell getprop ro.product.model)
                    echo ${device_model} ${line2}
                fi
            done

        fi
    done

    echo ""
}

This script will give you quick output about the speed for all devices you've connected on your computer.

➜ adbspeed
Checking connected Android device USB Speeds

SM-G960F [device-serial-1] connected with speed up to: 480Mb/s
Pixel 4 XL [device-serial-2] connected with speed up to: 5Gb/s

Gist

Test helpers

adbanimdisable

Disable all animations, and also mark the immersive_mode_confirmations to be already confirmed. Ensures those won't pop up the first time you test an immersive activity.

adbanimdisable() {
    adb shell settings put global window_animation_scale 0.0
    adb shell settings put global transition_animation_scale 0.0
    adb shell settings put global animator_duration_scale 0.0
    adb shell settings put secure immersive_mode_confirmations confirmed
}

adbanimenable

Reenable the animations on the phone

adbanimenable() {
    adb shell settings put global window_animation_scale 1.0
    adb shell settings put global transition_animation_scale 1.0
    adb shell settings put global animator_duration_scale 1.0
}

adbunlock

If the phone has a swipe screen lock, or a screen lock which requires the power button to be pressed, you can use this function. It works for situations when the phone has no pin to be entered.

This can also be super helpful if you had to restart a phone connected to a ci build agent, which you possibly have no physical access to, and still want to unlock the screen.

adbunlock() {
    adb shell input keyevent 82
    adb shell input keyevent 82
}

Extra

scrcpy

One of my most loved tools is scrcpy, thanks to the amazing people at Genymobile.

scrcpy provides display and control of Android devices connected on USB (or over TCP/IP). It does not require any root access. It works on GNU/Linux, Windows and macOS.

After installation just type scrcpy in your terminal and it will display your device with full control.

Use it to control the device, share your screen to your coworkers via a video call, or simply copy and paste text to and from the device.

Feedback

Do you have some scripts, additional tips and tricks to speed up various actions with adb or
thoughts, feedback, improvements, suggestions or comments?

Let me know @mike_penz

Attribution

Link preview photo by Jr. Farren / Unsplash