Bash your way to better Android Development

Jon F Hancock
Jon F Hancock
Published in
5 min readOct 24, 2016

--

When I work on Android projects, I usually have multiple devices connected. A blend of emulators and physical devices is great for checking app behavior. It also makes most of the adb command line actions useless. A few bash snippets can really save the day.

Using adb -s

For all of the commands we care about here, adb can easily perform the action on one device at a time if you supply the -s option and the identifier for the device you want to operate on. We want to operate on all devices, so we have to get the list of identifiers to work with. That takes a lot of ugly looking code, so let’s work through all of that first. Let’s start with the command we know: adb.

$ adb devices
List of devices attached
ZY2222NP55 device
192.168.56.101:5555 device

When we run adb devices, we can see the list of attached devices and a little bit of detail about them. Here I have a physical device, and a Genymotion emulator. This output is not ideal for looping over with a bash command though because of that extra data e.g. “device” and “List of devices attached” Let’s deal with these problems one at a time.

Using tail -n

First up is “List of Attached devices”. We can’t use that for anything. It’s just informational. So we’ll use tail to remove the first line. Actually two lines. The first one is just a newline. The second is “List of devices attached.”

$ adb devices | tail -n +2
ZY2222NP55 device
192.168.56.101:5555 device

Using cut -sf

Better already! Now we need to get rid of those pesky “ device” bits. For that, we’ll use cut. Cut let’s us loop over the lines provided, and remove certain parts of each line. We’ll cut the last word and any white space off the end of each line.

$ adb devices | tail -n +2 | cut -sf -1
ZY2222NP55
192.168.56.101:5555

Now that looks like something we can use! We now have a list of nothing but identifiers that adb can work with given the -s option. We can do stuff like:

adb -s ZY2222NP55 install -r MyAppRelease.apk

So now let’s figure out the best way to loop over this list of devices and operate on each of them with a single command. For that, xargs is the way to go.

Using xargs -I

Given the -I option, xargs will perform an action for each line of text that we feed into it. We can give the line a variable name to use in commands that xargs can execute.

$ adb devices | tail -n +2 | cut -sf -1 | xargs -I X echo X aw yiss
ZY2222NP55 aw yiss
192.168.56.101:5555 aw yiss

We can see here that we have told xargs to take each line of text (each identifier), and refer to it as X. Then execute the echo command with the identifier and the string “ aw yiss”. And xargs happily obliges.

Bringing it all together

Now that we understand how xargs works, we can use it in combination with adb -s to get some information about each device. Let’s use the adb shell getprop ro.build.version.release command to find the Android version of each device.

$ adb devices | tail -n +2 | cut -sf -1 | xargs -I X adb -s X shell getprop ro.build.version.release
6.0
6.0

Nice! We can see that they’re both running Marshmallow. Now we’re ready to execute any arbitrary command on every attached device! We just need two more things to make this user friendly.

Using alias

First, we need a shorthand for executing all this tail/cut/xargs nonsense. For that we use alias. Alias is really simple to use. It lets you define a new command, and have that command execute whatever comes after the = operator.

$ alias tellMeMore=echo
$ tellMeMore "hi there"
hi there

Now on my system, tellMeMore works exactly like echo.

Using bash command line arguments

Now we need a way to pass extra data to the command like the file name of an apk to install. Fortunately bash takes care of that for us. You can just use $1 to reference the first non-whitespace string after the command itself as a variable.

That brings us to our first fully formed alias!

Install an apk on all devices

alias apkinstall="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X install -r $1"

Android Studio makes it easy enough to deploy to multiple attached devices, but what if you have some other apk to install? Something you downloaded from a third party? After creating the alias above, you can invoke your new command, passing a path to an apk, and it will install it onto all attached devices. e.g.

$ apkinstall ~/Downloads/MyAppRelease.apk

Pretty painless!

Uninstall a package from all devices

Now what if we want to uninstall that app? Well annoyingly enough we have to know the package name, but that’s no different from using adb uninstall anyway.

alias rmapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X uninstall $1"

This command will remove the supplied application from all attached devices. e.g.

$ rmapp com.example.myapp

Clear data on all devices

Sometimes you want to leave the app installed but clear all of its data. Here’s a handy one for that.

alias clearapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell pm clear $1"

Now you can launch the app as if it were a fresh install really quickly after running:

$ clearapp com.example.myapp

Launch a deep link on all devices

Now the next one is my favorite when I want to launch a deep link on all attached devices.

alias startintent="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell am start $1"

I often find when I’m testing out intent filters for urls, I want to launch urls frequently and not bother with clicking a link in the browser on all of these devices. So I supply the url to the command, and watch it go. e.g.

$ startintent https://twitter.com/JonFHancock

Setting up your .bash_profile

Finally, to make this all reusable even after rebooting your computer (aliases only last through the current session), we have to add these to your .bash_profile. You might or might not already have a .bash_profile, so let’s make sure we append to it rather than overwriting it. Just open a terminal, and run the following command

touch .bash_profile && open .bash_profile

This will create it if it doesn’t already exist, and open it in a text editor either way. Now just copy and paste all of the aliases into it, save, and close.

alias startintent="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell am start $1"
alias apkinstall="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X install -r $1"
alias rmapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X uninstall $1"
alias clearapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell pm clear $1"

So what shortcuts do you like to use from the command line? Share your aliases in the comments!

--

--