Utilizing ADB for daily tasks

If you’re developing Android apps, you might often wonder how does our PC communicate with the Android devices when we debug. Well, the answer is through the Android Debug Bridgeadb for short. When you run your app, the computer install the debug apk with adb install and launch the app with adb am start (am stands for activity manager more on that belows). But there’s more to adb than that meets the eyes, in fact, some of the commands can help your day-to-day activities.

Installing ADB

First thing first, try running adb in your terminal to make sure it’s installed on your system. If you see something along the line of command not found, that means adb is not installed yet. For MacOS, running brew install android-platform-tools should be okay. For the rest (and for MacOS as well if you prefer manual) you can follow these steps

  1. Download platforms-tools here
  2. Unzip it somewhere you want to keep it (preferably ~/Android/platform-tools)
  3. Then in your shell config ( ~/.bashsrc~/.zshrc etc.) Add the following lines (For Windows, you might need to add the path inside System variables) :
export PATH=${PATH}:$YOUR_EXTRACTED_PATH/platform-tools

We will have to reload the shell (close and open terminal) afterwards.Then try running adb again. If it works, then we can continue ahead to explore some of its usefulness.

Setting up Physical device Debugging

If you’re using a physical device, you will need to enable USB debugging in the device. First, enable Developer Options by going into System => About, and tap Build Number seven times. Some devices has different ways to enable Developer Options, so Google for your device if the common step doesn’t work. Afterwards, go into Developer Options and enable “USB Debugging“.

Then, plug your device into your PC and execute adb devices in the terminal. See if your device name pops up.

It should shows up like this

If it doesn’t, it could either be your PC not recognizing your device (especially on Windows where you will need a driver) or USB Debugging has not been enabled. If this is your first time connecting through adb, you might also need to authorize your PC in your Android device which should shows up with a pop-up dialog. Don’t worry, you can revoke the access in Developer Options later. If your device is showing up after adb devices, then we can proceed.

If you want to go one step further, we can setup in a way USB cable is obsolete. You can enable Wireless ADB Debugging in Developer Options. After that,

  • Connect your device to PC with USB
  • Run adb tcpip 5555 to make it listen to port 5555.
  • Run adb shell netcfg or adb shell ifconfig to see your Android device’s IP
  • Disconnect USB
  • Run adb connect $DEVICE_IP:5555 to connect to your device wirelessly

Make sure to run adb usb after as leaving it open in the (especially public) network is dangerous

On Android 11 and above, Android now has a function to make wireless debugging easier where a device can pair wirelessly with pairing code or QR code without the need of plugging into the PC for the first time. Tap on Wireless Debugging and it will shows you a similar screen as follows:

Tap on “Pair device with pairing code and you will see a popup similar to the one below:

Go to terminal and run adb pair $DEVICE_IP_AND_PORT $PAIRING_CODE. And it should connect your phone.

~ adb pair 192.168.1.39:39005 954121
Successfully paired to 192.168.1.39:39005 [guid=adb-ec54c0bd-nyDhpf]

Push & Pull files

If you ever been on a Mac, you would be familiar with Android File Transfer. And for Linux and Windows, we can manually find the file and copy paste it onto our computer. However, I prefer transferring file through adb since it saves me the hassle of having to connect with USB.

If we want to transfer from my PC to the device, we can utilize adb push command.

adb push $FILE_IN_YOUR_PC$ $PATH_IN_YOUR_DEVICE$

For example, if I want to push a document into device, I can run

adb push ~/document.txt /sdcard/document.txt

Reversibly, We can execute adb pull for transferring from device to PC.

adb pull $FILE_IN_YOUR_DEVICE$ $FILE_IN_YOUR_PC$ 
adb pull /sdcard/document.txt ~/document.txt

With adb, you don’t need to use cables, emails, AirDroid or any other tools for you to transfer to/from your device again.

Automating login

adb can also be used to automate filling forms when you’re doing manual testing. adb allows you to send input commands to the device. These inputs could be either just tapping, typing text or sending a key event like ENTERTAB etc. Let’s take a look into this scenario where I would need to type user1 and password1 .

Example Login

We can input text onto the username or password fields with the following command

adb shell input text $YOUR_TEXT$
adb shell input text user1 && adb shell input text password1

If you run the command in the terminal, you will see that it’s not exactly right. password1 is being appended after the end of user1. That’s because we haven’t shift the focus of the text input yet. We have to switch it from username input to password input. To do this, assuming you have proper nextFocus attributes in your inputs, we can send a TAB_EVENT to the device to switch between inputs. You can find all the possible input event codes here and if you scroll down, you will see KEYCODE_TAB is set to 61. For key event, we have to use input keyevent $KEY_EVNET_CODE. It would looks like this

adb shell input keyevent 61

If we combine all of these, we will have the following one liner that will automatically type the credentials for our testing account

adb shell input text user1 && adb shell input keyevent 61 && adb shell input text password1
✨✨✨

If you have captured the ENTER key event to start login, we can even use input keyevent 66 to press Enter, and start login with zero manual tap.

Personally, I make an alias for repeated form filling in my shell config because it reduces time for me during manual tests. Plus, it looks like magic in presentations and demos when you see a small command like testAccountLogin being executed and everything just works.

alias testAccountLogin = adb shell input text user1 && adb shell input keyevent 61 && adb shell input text password1

I have said that the above example assumed that you have proper nextFocus attributes in your inputs. But what if you’re testing for a third-party app and the app doesn’t really has proper nextFocus? How do we automate switching between the inputs? No worries, we can still use input tap $X_VALUE $Y_VALUE to tap the screen. There’s two ways, the first one involve

  1. Run adb shell getevent -l in the terminal to log the input events
  2. Manually press your input field
  3. Check if there’s ABS_MT_POSITION_X and ABS_MT_POSITION_Y in the terminal
  4. Copy the value (they should be in hexadecimal)
  5. Convert the values into decimal value
  6. Run adb shell input tap $DECIMAL_X $DECIMAL_Y to see if it’s click on the input field

This involves some complex steps, so, I prefer to use more straightforward way.

  1. Open Developer Options
  2. Enable Input > Pointer Options
  3. Check if you can see numbers at the top of the screen
  4. Hold your finger or put the cursor over the input field
  5. Copy the x, y value (usually at top left corner of the screen)
  6. Run adb shell input tap $dx $dy to see if it’s click on the input field

In our example, I can also use tap command to do the same thing

adb shell input text user1 && adb shell input tap x y && adb shell input text password1

This works for anything on the screen, including buttons. A full command that includes tapping loign button would be as follows:

adb shell input text user1 && adb shell input tap x y && adb shell input text password1 && adb shell input tap x y
With tap instead of key event
  • adb shell input tap 300 700 – Inputs a tap event at the specific coordinates in pixels. In this case, 300 is the x value and 700 is the y value.
  • adb shell input swipe 540 1600 540 100 1500 – Inputs a swipe gesture starting at a set of coordinates, ending at another set of coordinates. In this case, 540 is the start x value, 1600 is the start y value, 540 is the end x value, 100 is the end y value, and 1500 is the time in milliseconds the swipe will take. On both a physical device and the emulator I have found that swipe inputs that are under 1500 milliseconds produce inconsistent results. This is important because when chaining multiple inputs together (more on this below), if one of them is off, the whole chain is broken.
  • adb shell input text 'Leon' – Inputs text.
  • adb shell input keyevent 66 – Inputs enter.
  • adb shell input keyevent 19 – Inputs a D-pad up event, useful for changing the focus to a different view.
  • adb shell input keyevent 20 – Inputs a D-pad down event, useful for changing the focus to a different view.
  • adb shell input keyevent 21 – Inputs a D-pad left, useful for changing the focus to a different view.
  • adb shell input keyevent 22 – Inputs a D-pad right event, useful for changing the focus to a different view.
  • sleep 1 – Pauses execution for a specified amount of seconds. In this case, execution would pause for one second. Though this is not an adb command (it’s a shell command), it is useful for waiting for an animation to complete or data to be received from the server, before continuing with other adb inputs.
  • adb shell input keyevent 26 -To simulate pressing the hardware power key
  • adb shell input keyevent POWER
  • adb shell input keyevent CAMERA

Even if you don’t have a hardware key you still can use a keyevent to perform the equivalent action

adb shell input tap 750 300                 # tap search bar
sleep 1                                     # wait for load
adb shell input text 'echo'                 # input search
adb shell input keyevent 66                 # executue search
sleep 2                                     # wait for search to load
adb shell input tap 700 800                 # tap product
sleep 4                                     # wait for load
adb shell input tap 740 2200                # tap color options
sleep 1                                     # wait for load
adb shell input tap 820 1460                # tap white
sleep 1                                     # wait for load
adb shell input tap 1290 960                # tap done
sleep 1                                     # wait for load
adb shell input swipe 540 1600 540 100 1500 # scroll down
adb shell input swipe 540 1600 540 100 1500 # scroll down
adb shell input tap 720 800                 # add to cart
sleep 1                                     # wait for load
adb shell input tap 1350 150                # open cart
sleep 2                                     # wait for load
adb shell input tap 800 480                 # start checkout
adb shell input text "We\ are\ the\ best\!" # Inputs text with ""
adb shell input text 'this%sis%san%sexample' # Input text with ''

Screenshot and video record

Another common task is taking screenshots and recording video. These are useful when you want to report an issue and want to show the replication steps clearly. Let’s start with screenshot first.

adb shell screencap $PATH_IN_DEVICE

For example, we can run adb shell screncap /sdcard/our_screencap.png. We can then execute adb pull /sdcard/our_screencap.png to pull the screenshot into our PC.

For video recording, we can execute

adb shell screenrecord $PATH_IN_DEVICE

When we’re done recording, we can press Ctrl+C (or Command+C on MacOS) to stop the recording. Similar to above, we can also run adb pull to pull the file onto our development PC after recording. Additionally, we can provide options such as resolution, bitrate, time etc. You can browse these options here. Do note that there are limitation to this approach such as you cannot rotate the screen during recording and that audio won’t be captured.

Testing DeepLinks

Deep links are one of those few things tedious to test because manually, you have to click on the links in some third party app to see if your app is correct in handling the links. We can remove this need of third party apps by testing this function through the use of adbAs mentioned in this documentation, you can run the following command

adb shell am start
-W -a android.intent.action.VIEW
-d <URI> <PACKAGE>

adb shell am start
-W -a android.intent.action.VIEW
-d "example://gizmos" com.example.android

To break this command down,

  • am means activity manager. To make it simple, in Android, each app has an activity or multiple activities that hosts the UI that the user can see. Activity Manager knows which apps has which activities and we can launch specific screen/activity through the activity manager.
  • -W means wait for the launch to be completed.
  • -a android.intent.action.VIEW is where we specify the action that we want to execute. In Android, we have predefined actions that the OS understand and the OS can use this information to route the acti0n to the corresponding apps. If you ever open a file and wonder where all of these apps are coming from in the popup, then the answer is through this OS feature. The OS knows which app can handle which file, i.e, which action.
  • -d <URI> <PACKAGE> : destination specify two parameters, first is our deep link uri, and the second one is the app we want to view this deeplink on. For the first one, replace with the link you want to test, and for the second, you can enter your app’s package name.

If you run that command, the OS should launch your app. First, OS will first ask the app if it can handle this type of deep link. If the app can handle the deep link, it will receive the deeplink, and now the app is responsible for dissecting the deep link and manage it.

By navalkishorjha

Leave a comment