Install and run an Android app on every connected device

I usually have only one device connected when I develop non-UI related parts of the app, but when it comes to UI, I tend to try out the app on as many devices as possible.

There was a time when I actually had physical devices connected all the time (https://ivanmorgillo.com/2016/01/05/first-hardware-project-of-2016-device-holder/), but lately I have been using emulators.

Last week I realized that something changed in my workflow about how I was running the app on multiple devices. Android Studio/IntelliJ has a drop down menu where you select the option:

Once you select “Run on Multiple Devices”, you get a second menu where you select the devices:

You click Run and everything gets built and deployed on every device.

Problem is… it doesn’t remember the selection. There is no way to keep running on multiple devices. You need to open the menu again and go through the two dialogs. That’s too much clicking for me.

OK, I’m Cmd + Shift + A the hell out of it!

Well, not really 😞 The worst part is that you can’t reach the action from the menu:

Deep down I remembered that we had such feature on AS, but why I can’t find it? I looked it up and it turns out, the feature was removed 🤦🏻‍♂️ I don’t even… Anyway, I got it.

Command line solution

Run on multiple devices is basically replicating two commands on every connected device:

  1. Install the app
  2. Launch the LAUNCHER Activity

Installing on every device

From a terminal we can install on every device with:

./gradlew installDebug

BOOM. Done. Piece of cake. Next, please.

Launching the app

You can launch the app on the only connected device using adb:

adb shell am start -n you.package.name/.YourLauncherActivity

The package name in your build.gradle and the LAUNCHER Activity is specified in your AndroidManifest.xml.

You can launch the app on a specific device with:

adb -s DEVICE_ID shell am start -n your.package.name/.YourLauncherActivity

Gathering device IDs

To get the device IDs we can use this command:

adb devices | tail -n +2 | cut -sf 1 | xargs -I {}

This is some exoteric command line-fu. I wouldn’t waste time trying to understanding it. I won’t understand it neither in 5 days. I “Try&Error“-ed until it worked and that’s why I’m writing this blog post:

We are not meant to remember things that can be written down. We are meant to solve problems with creativity 😃

Putting everything together

To install on every device and launch on every device, we can use the combination of all these commands:

./gradlew installDebug && adb devices | tail -n +2 | cut -sf 1 | xargs -I {} adb -s {} shell am start -n your.package.name/.YourLauncherActivity

Improvements

The Alias

You could create an alias:

alias runMyAppEverywhere="./gradlew installDebug && adb devices | tail -n +2 | cut -sf 1 | xargs -I {} adb -s {} shell am start -n your.package.name/.YourLauncherActivity"

and put it in your ~/.bash_profile or ~/.zshrc.

The Script

You could also create a script that you can reuse for multiple projects. Create a runEverywhere file and add this:

#!/bin/bash

./gradlew installDebug && adb devices | tail -n +2 | cut -sf 1 | xargs -I {} adb -s {} shell am start -n $1

Make it executable with:

chmod +x runEverywhere

Use it like this:

./runEverywhere your.package.name/.YourLauncherActivity

Conclusions

UIs are cool, but when they fall short, you can probably find a solution using the console 💪🏻

Happy coding, my friend 😉

Advertisements

Leave a Reply