Monday, January 31, 2011

Obtaining Android screenshots in tests with monkeyrunner

Today I helped somebody that was asking why an extremely simple monkeyrunner script fails to obtain the screenshot.
Interestingly enough, this script was almost a verbatim copy of what is specified in monkeyrunner documentation. So you guessed, the documentation is wrong and unfortunately there is no way of correcting it, Android documentation is not a wiki and the only way is reporting a bug that will be probably ignored sunk in a sea of thousands more important bugs.

So here you have the problem and the solution.

The problem
The documentation includes this line to take the screenshot:


# Takes a screenshot
result = device.takeSnapShot

if you run this, you soon realize that something is wrong. You will receive an error similar to this one:

AttributeError: 'com.android.monkeyrunner.adb.AdbMonkeyDevice' object has no attribute 'takeSnapShot'

The problem, or better I should say the problems, because there are two, are:
  1. missing parenthesis, so instead of using the call operator on the callable object we are getting a reference to the object itself and then try to access one attribute
  2. if there were parenthesis, the call won't succeed anyway because the second 'S' is lowercase 's'


The solution
Then this is the complete solution to obtain the screenshot:


# Imports the monkeyrunner modules used by this program
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
# Connects to the current device, returning a MonkeyDevice object
device = MonkeyRunner.waitForConnection()
# Takes a screenshot
result = device.takeSnapshot()
# Writes the screenshot to a file
result.writeToFile('/tmp/device.png','png')


Extra tip
You can add the corresponding she-bang to the script and set the execution permission to be able to run it from the command line just invoking the script name:


#! /opt/android-sdk-linux_86/tools/monkeyrunner
...
This should include the path to your monkeyrunner script, and because it uses Jython, an implementation of Python that uses the Java programming language, thus allowing the use of Python syntax to access the constants, classes, and methods of the API.
Having added this she-bang line you can simply run your monkeyrunner script by invoking its name:

  $ monkeyrunner-take-screenshot

Friday, January 14, 2011

Alternative logcat viewer

If you are developing Android with Eclipse and have several devices and emulators connected you may have been annoyed by the constant disconnection that the DDMS view suffers, in such cases you could try to reconnect to the desired device by clicking on it, but this is not always successful.

I've found as a workaround that sometimes is easier to reconnect if you reach another device or emulator first and then the desired one, so as a rule of thumb is probably better to always have more than one.

Anyway, here you are a very simple trick that might turn you life a little easier just using a text logcat from adb in a gnome-terminal that will remain open no matter what have happened to the connection.

First, you need to create a gnome-terminal profile, logcat in this case, an set the following values as dispalyed:


The important things here are:

  • Run a custom command instead of my shell
  • Custom command: sh -c '/opt/android-sdk/platform-tools/adb -e logcat | coloredlogcat.py'
  • When command exits: Hold the terminal open
As a bonus, we are including coloredlogcat.py, a filter that will colorize our logcat output.
What's nice about this simple setup is that even if you are disconnected because you closed the emulator or unplugged the device, just clicking on the Relaunch button will reconnect you again.


Hope you enjoy it and improve your development not having to insistently click on DDMS'  device list.