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:
- Install the app
- 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 😉