Last week I started playing a new game on my phone called Castle Crash. I don’t play often play video games but when I do, I play them obsesively until they are defeated. In this case you can’t beat the game since you are playing against the internet so I decided to tap out and let my computer take over.
Android has a great tool for writing simple automated tests on a device called MonkeyRunner. It uses Jython to let you write Python scripts that simulate user interactions and events on your device. MonkeyRunner can be found in the tool directoy after you have installed the Android SDK.
Determine Apps Package/Activity
To determine an apps package/activity the easiest way is to download the .apk file, decompress it and take a look at the AndroidManifest.xml. Alternatevly you can run the app on your device and watch the logs.
Long pressing is a pretty standard user interaction but MonkeyRunner doesn’t really support it. It does however support .drag() which can be used for the same purpose.
device.drag((x,y), (x,y), pressTime)
Exiting the app is a good way to reset back to a known state and can be done between actions if the game structure allows.
device.shell('am force-stop ' + package)
Determine Interaction Coordinates
Since MonkeyRunner doesn’t know anything about the app that is running it works solely with pixel coordinates. This means that you need to determine the location of all elements on the screen you want to interact with and there are a few ways of doign this. The most basic way is to determine the size in pixels of your device and then start estimating from there. This actually works quite well once you get the hang of it. A more accurate method is to enable ponter locations on your device(under developer options) and then walk through the flow keeping track of each required action.
Some Bot Code
This code replenishes the four troop camps in Castle Crash and is a good example of simple interactions with the game.
def replenishTroops(campNumber)\: print 'replenishing troops' campLocations = [(320, 400), (320, 120), (590, 80), (560, 350)][campNumber] touch(campLocations, campLocations) #select camp touch(480, 450) #press hire button device.drag((300, 450), (200, 450)) #scroll to archers time.sleep(5) #wait for scroll to finish device.drag((500, 450), (501, 451), 5) #long press archers button touch(660, 60) #close areana window touch(5, 5) #deselect anything def touch(x, y, delay=2)\: print('touching ' + str(x) + ', ' + str(y)) device.touch(x, y, 'DOWN_AND_UP') time.sleep(delay)