Automating Input Events on Android

Gears

On a recent client project I became frustrated with manually navigating to a certain part of the app every time in order to test it. This happened to be an ecommerce app which had many screens and quite a long user flow end to end. One of the components of the app I worked on was checkout. In order to navigate to the order review screen the following steps are required: Navigate to a product, if applicable choose a size and/or color, add the product to your shopping bag, open the shopping bag, initiate the checkout process, add shipping info, add billing info, and finally add payment info. You can imagine how time consuming and annoying it would be to have to go through this process every time. Thanks to a colleague I discovered I could automate this entire process using shell scripts and adb commands. The following examples have been tested on macOS, and may work on linux or Windows depending on your configuration.

ADB Input Events

An adb input event allows you to send certain events like taps or swipes to the device. All the possible input events you can send are documented both here and here. Here are some that I have found useful:

  • 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.

Automating Input Events w/ Shell Scripts

To string together multiple input events put them in a shell script. On macOS open up TextEdit, add the input events each on a separate line, and save the file with the .sh extension. Then with an emulator or physical device connected, in Terminal navigate to the .sh file and execute it with sh ./add.sh where add.sh is the name of your shell file.

Using the Amazon app as an example, here is what my shell script looks like to add an item to the shopping bag from the home screen and initiate the checkout process:

Here is what it looks like (I have enabled pointer location in the developer settings to make it easier to see the tap and swipe events):

Besides my add.sh, I have a create.sh, which handles creating a new account. I also have an all.sh which runs each step sequentially. This is a great way to break up each one of your steps and then combine them as needed. For this example, I have only created bash scripts for adding an item to the cart and then creating an account. For my actual project I also had scripts for adding payment info, shipping info, and finally one for completing the checkout process. It is easy to imagine how flexible these scripts can be.

Tips

  • Since the input events are coordinate specific, they will not work on all devices. If you are sharing these with a team, decide which device you want to target. That is why going with an emulator is a solid option, because anyone on your team can create one without needing a physical device.
  • Enable pointer location in developer options to easily determine the coordinates of input events.
  • Press Ctrl + C to stop a shell script while it is executing.
  • As a team you may decide to even include shell scripts in your repo for handling repetitive flows. Then, you can user the terminal integrated right into Android Studio to easily access the shell scripts.
  • Use # to add comments to your shells scripts.
  • Be careful. I accidentally ordered an Echo Dot.

If you enjoyed this post, you can follow me on Twitter @dickclucas, where I talk about Android, technology, and other related topics. Feel free to ask questions in the comments!


Do you have a project in mind? We’d love to work with you. If you’d like an opportunity to work on projects with us, check out our Careers page. We’re hiring!

2 thoughts on “Automating Input Events on Android”

  1. This is very helpful. I just got done figuring out how to correctly tap & swipe, before finding your post. I need to script it, and this article is very helpful. Thanks! I need to write a loop that keeps tapping ( refresh button), until an item appears on the screen, then swipe. Ideally, I only want to swipe if the item has desired property(s). So, I need some sort of conditional, or if statement.

  2. Can you tell me how to swipe only if a certain item appears on screen?

    pplus:/ $ input tap 720 2300
    pplus:/ $ input swipe 1400 2300 1 2300
    pplus:/ $ echo YAY!!! THAT WORKED!!!
    YAY!!! THAT WORKED!!!

    I figured that out, before discovering this webpage. Now that I found your post, I might add the “1500” to the end of the swipe.

    I’m guessing there’s probably an adb command to return properties of any object at a given coordinate, and use bash to tap, or swipe, if properties meet certain criteria, or exist at all.

    1500ms is way too long for me, though. Maybe I need to root my device, and install a local script, but even response time with tasker+autoinput is a disappointment. It’s very unreliable, like you said.

    Thanks!
    Michael

Leave a Comment