Category Archives: Android MonekyRunner

Script for doing screen captures

Created a screen for doing screen captures, so I can call it while doing other test.  This script uses the time to create an unique file name, so I don’t have to worry about overwriting the same file while running my test.  This script is run by monkeyrunner so I used the full path when calling monkeyrunner and my script (this is a bit bias towards OS X syntax since I am testing on a Mac at the moment)

/Users/me/Android/sdk/tools/monkeyrunner -v ALL  /Users/me/Android/capture_screen.py

-v ALL is for verbose logging

#!/usr/bin/env python
# coding: utf-8

# Screen shot of android

# Needed modules
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice

import time

# Wait for connection
device = MonkeyRunner.waitForConnection()

# Use the time in seconds to help create an unique file name for the image that is captured

filelocation = "/Users/jmiller/Android/Screen_Shots/"

fileNamePrefix = "scrnCap"

thefile = filelocation + fileNamePrefix + str(int(time.time())) + ".png"

# Snap shot of the screen
result = device.takeSnapshot()

# Write out the results
result.writeToFile(thefile,"png")
Advertisements

Turning the output from getevent into something something that can be used

My end goal was to to be able to “doodle” on the android screen, with a script.  I can’t do the math to generate the image I want, so I ran the adb shell command “getevent” then using the mouse, I drew on the screen.

However the output isn’t immediately usable, first there was the minor problem of it containing a colon which would throw an error when I tried to run it.  The second and bigger issue, is that the getevent command captures everything in hexadecimal, but the command sendevent, requires everything to be in decimal.  Since monkeyrunner is basically python (the docs say jython, but I haven’t used anything that advance yet), I wrote a python script, that takes an input file containing a bunch of lines that look like this:

/dev/input/event0: 0003 0000 00000073
/dev/input/event0: 0003 0001 000000a8
/dev/input/event0: 0001 014a 00000001
/dev/input/event0: 0000 0000 00000000
/dev/input/event0: 0003 0001 000000a4

And created a new output file with adb shell commands that look like this:

adb shell sendevent /dev/input/event0 3 0 115
adb shell sendevent /dev/input/event0 3 1 168
adb shell sendevent /dev/input/event0 1 330 1
adb shell sendevent /dev/input/event0 0 0 0
adb shell sendevent /dev/input/event0 3 1 164

Which can be run and do the drawing for me on the screen.  This worked, but running a bunch of adb shell commands is really, really slow.  So I tweaked my python script, and instead have to create something like:

#!/bin/sh
echo Running – signature function
sendevent /dev/input/event0 3 0 115
sendevent /dev/input/event0 3 1 168
sendevent /dev/input/event0 1 330 1
sendevent /dev/input/event0 0 0 0
sendevent /dev/input/event0 3 1 164
sendevent /dev/input/event0 0 0 0
……..

This is copied to the device, and run as a local script and runs at an ok speed (not really fast, but much faster than adb shell commands) – the python script prints out instructions with the exact command to run, to copy the file to the device and what to execute it run it.  I will post the python separately, I am new to this code so the code isn’t prefect, but it works and meets my needs.ew

The steps are

  1. Run the app (I did it in the emulator)
  2. Run the command adb shell getevent, om whatever screen you want to doodle/draw on – the output is dumped to the screen
  3. Capture that output when you are done (copy it, usually by right clicking and choosing mark, highlight the area and then hit enter)
    1. Paste the info into notepad, and save it to any file name you want (i.e. captured.dat)
  4. Run the script
    1. hex_to_dec.py captured.dat
      1. catpured.bat is the input data for the script
  5. The script runs pretty fast and kicks out a file captured.scr (the code can be updated to name the file anything)
    1. The script prints out instructions for coping the script to the device and for running the script, that looks something like this

C:\>hex_to_dec.py raw_captured_sig.dat
Processing complete
File created: raw_captured_sig.scr

Copy file to the device
adb push raw_captured_sig.scr /sdcard/raw_captured_sig.scr

Run the script
adb shell sh /sdcard/raw_captured_sig.scr

Monkeyrunner links & Other automation info

Some links for Monkeyrunner

From the Android site (though it took tweaking to make this work for me)

monkeyrunner | Android Developers – http://developer.android.com/guide/developing/tools/monkeyrunner_concepts.html

 

Additional Documentation from Android

Monkey Device – other program options, like reboot – http://developer.android.com/guide/developing/tools/MonkeyDevice.html
Monkey Image – Pixel and Image stuff –  http://developer.android.com/guide/developing/tools/MonkeyImage.html
Monkey Runner – has some static utility methods. – http://developer.android.com/guide/developing/tools/MonkeyRunner.html

 

Some Other UI Automation Ideas

Android UI Automation Basics – http://goravsingal.hubpages.com/hub/Android-UI-Automation-Basics

 

Python

Python/Jython Downloads – http://www.python.org/download/

Alternatives to Eclipse (which isn’t my favorite beast)

I have been using Notepad++ to write my early learning scripts (though this isn’t an IDE)

Netbeans another IDE

 

Other tools

Robotium – (I felt this needed a lot of developer support in order to me to work with it and I am not a Java person) – http://code.google.com/p/robotium/ – and it integrates with Cucumber but that requires Ruby

 

Paid tools (e.g not free)

TestDroid – http://testdroid.com/

monkeyrunner snapshot file location

Inside my script I wanted to do a snapshot and have the image stored in my local directory where I was running the script.  Once again I ran into the problem, where monkeyrunner thinks every is local to the directory where located, not where it is launched from.  So in the python code I need to put the full path to where I want the image stored.  But that failed do to me being a silly Windows user and typing the path with back slashes “C:0001101\Android\” to make it work I need to use forward slashes like in linux/unix “C:/00001101/Android/”

So the line of code looks like this:

result.writeToFile(‘C:/00001101/Android/dashboard.png‘,’png’)

 

Running a monkeyrunner script with verbose logging

Found a couple annoying things, first no matter where I am running monkeyrunner from, it thinks everything is local to is, so I have to put in the complete path to my script, even though I am running from the directory where the script is

Example (my script when I run it)

C:\Android>monkeyrunner -v ALL C:\Android\SCRIPT_signin.py

The next problem is the logging “-v” there are several logging options, however the key thing to remember is that it is case sensitive (which to me lame, “all” should equal “ALL” – but it doesn’t)

 Logging levels (ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF)

 

AdbChimpDevice: Error starting command

I have a simple monkeyrunner script, that runs correctly for that I need, but often hits this error:  AdbChimpDevice: Error starting command, and it doesn’t always happen in the same place.  From the source code I looked at, there was a comment that exception happens a lot, yet in my case the script still ran fine.

Something that can be ignored even though it is ugle

What the error looks like in verbose debugging

[com.android.chimpchat.adb.AdbChimpDevice] Error starting command: monkey –port 12345
[com.android.chimpchat.adb.AdbChimpDevice]com.android.ddmlib.ShellCommandUnresponsiveException
[com.android.chimpchat.adb.AdbChimpDevice]      at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:408)
[com.android.chimpchat.adb.AdbChimpDevice]      at com.android.ddmlib.Device.executeShellCommand(Device.java:388)
[com.android.chimpchat.adb.AdbChimpDevice]      at com.android.chimpchat.adb.AdbChimpDevice$1.run(AdbChimpDevice.java:105)
[com.android.chimpchat.adb.AdbChimpDevice]      at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
[com.android.chimpchat.adb.AdbChimpDevice]      at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
[com.android.chimpchat.adb.AdbChimpDevice]      at java.util.concurrent.FutureTask.run(Unknown Source)
[com.android.chimpchat.adb.AdbChimpDevice]      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
[com.android.chimpchat.adb.AdbChimpDevice]      at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
[com.android.chimpchat.adb.AdbChimpDevice]      at java.lang.Thread.run(Unknown Source)

 

 

Running a test script

Apparently monkeyrunner is brain dead if you run it like this:

monkeyrunner test.py

It will fail with the error:

Can’t open specified script file
Usage: monkeyrunner [options] SCRIPT_FILE

-s      MonkeyServer IP Address.
-p      MonkeyServer TCP Port.
-v      MonkeyServer Logging level (ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF)

This is due to monkeyrunner looking for the script where monkeyrunner is located not where you running it from. So instead of looking for my test.py file in C:0001101\Android> it looks for it where monkeyrunner is in C:\Program Files (x86)\Android\android-sdk\tools

To fix this include the path with the script (lame)

monkeyrunner C:001101\Android\test.py

Then it will run (though my script doesn’t really work yet)

Update: It looks like my basic script worked, “worked” meaning it launched the app, which is the only thing it does at the moment, and I am running this in the emulator.

Monkeyrunner API Reference

Update:  I always get errors when I try and use monkeyrunner.sleep(xx) – however I can import time, and use time.sleep(xx) without a problem

 

API Reference 05-24-2012 (adding the date for when and if it changes in the future) – no formatting this is how it is dumped to the file when doing “text”

MonkeyRunner help

com.android.monkeyrunner.MonkeyRunner.alert
Display an alert dialog to the process running the current script.  The dialog is modal, so the script stops until the user dismisses the dialog.

Args:
message – The message to display in the dialog.
title – The dialog’s title. The default value is ‘Alert’.
okTitle – The text to use in the dialog button. The default value is ‘OK’.
Returns: returns nothing.

com.android.monkeyrunner.MonkeyDevice.broadcastIntent
Sends a broadcast intent to the device.

Args:
uri – The URI for the Intent.
action – The action for the Intent.
data – The data URI for the Intent
mimetype – The mime type for the Intent.
categories – An iterable of category names for the Intent.
extras – A dictionary of extras to add to the Intent. Types of these extras are inferred from the python types of the values.
component – The component of the Intent.
flags – An iterable of flags for the Intent.All arguments are optional. The default value for each argument is null.(see android.content.Context.sendBroadcast(Intent))
Returns: returns nothing.

com.android.monkeyrunner.MonkeyRunner.choice
Display a choice dialog that allows the user to select a single item from a list of items.

Args:
message – The prompt message to display in the dialog.
choices – An iterable Python type containing a list of choices to display
title – The dialog’s title. The default is ‘Input’
Returns: The 0-based numeric offset of the selected item in the iterable.

com.android.monkeyrunner.MonkeyImage.convertToBytes
Converts the MonkeyImage into a particular format and returns the result as a String. Use this to get access to the rawpixels in a particular format. String output is for better performance.

Args:
format – The destination format (for example, ‘png’ for Portable Network Graphics format). The default is png.
Returns: The resulting image as a String.

com.android.monkeyrunner.MonkeyDevice.drag
Simulates dragging (touch, hold, and move) on the device screen.

Args:
start – The starting point for the drag (a tuple (x,y) in pixels)
end – The end point for the drag (a tuple (x,y) in pixels
duration – Duration of the drag in seconds (default is 1.0 seconds)
steps – The number of steps to take when interpolating points. (default is 10)
Returns: returns nothing.

com.android.monkeyrunner.MonkeyView.getAccessibilityIds
Returns the accessibility ids of the current view

Returns: The accessibility ids of the view as a list of ints

com.android.monkeyrunner.MonkeyRect.getCenter
Returns a two item list that contains the x and y value of the center of the rectangle

Returns: The center coordinates as a two item list of integers

com.android.monkeyrunner.MonkeyView.getChecked
Get the checked status of the view

Returns: A boolean value for whether the item is checked or not

com.android.monkeyrunner.MonkeyView.getChildren
Returns the children of the current view

Returns: The children of the view as a list of MonkeyView objects

com.android.monkeyrunner.MonkeyView.getEnabled
Returns the enabled status of the view

Returns: The enabled status of the view as a boolean

com.android.monkeyrunner.MonkeyView.getFocused
Returns the focused status of the view

Returns: The focused status of the view as a boolean

com.android.monkeyrunner.MonkeyRect.getHeight
Returns the height of the rectangle

Returns: The height of the rectangle as an integer

com.android.monkeyrunner.MonkeyDevice.getHierarchyViewer
Get the HierarchyViewer object for the device.

Returns: A HierarchyViewer object

com.android.monkeyrunner.MonkeyView.getLocation
Returns the location of the view in the form of a MonkeyRect

Returns: The location of the view as a MonkeyRect object

com.android.monkeyrunner.MonkeyView.getParent
Returns the parent of the current view

Returns: The parent of the view as a MonkeyView object

com.android.monkeyrunner.MonkeyDevice.getProperty
Given the name of a variable on the device, returns the variable’s value

Args:
key – The name of the variable. The available names are listed in http://developer.android.com/guide/topics/testing/monkeyrunner.html.
Returns: The variable’s value

com.android.monkeyrunner.MonkeyDevice.getPropertyList
Retrieve the properties that can be queried

Returns: returns nothing.

com.android.monkeyrunner.MonkeyImage.getRawPixel
Get a single ARGB (alpha, red, green, blue) pixel at location x,y. The arguments x and y are 0-based, expressed in pixel dimensions. X increases to the right, and Y increases towards the bottom. This method returns a tuple.

Args:
x – the x offset of the pixel
y – the y offset of the pixel
Returns: A tuple of (A, R, G, B) for the pixel. Each item in the tuple has the range 0-255.

com.android.monkeyrunner.MonkeyImage.getRawPixelInt
Get a single ARGB (alpha, red, green, blue) pixel at location x,y. The arguments x and y are 0-based, expressed in pixel dimensions. X increases to the right, and Y increases towards the bottom. This method returns an Integer.

Args:
x – the x offset of the pixel
y – the y offset of the pixel
Returns: An unsigned integer pixel for x,y. The 8 high-order bits are A, followedby 8 bits for R, 8 for G, and 8 for B.

com.android.monkeyrunner.MonkeyDevice.getRootView
Obtains current root view

Returns: The root view object

com.android.monkeyrunner.MonkeyView.getSelected
Returns the selected status of the view

Returns: The selected status of the view as a boolean

com.android.monkeyrunner.MonkeyImage.getSubImage
Copy a rectangular region of the image.

Args:
rect – A tuple (x, y, w, h) describing the region to copy. x and y specify upper lefthand corner of the region. w is the width of the region in pixels, and h is its height.
Returns: a MonkeyImage object representing the copied region.

com.android.monkeyrunner.MonkeyDevice.getSystemProperty
Synonym for getProperty()

Args:
key – The name of the system variable.
Returns: The variable’s value.

com.android.monkeyrunner.MonkeyView.getText
Returns the text contained by the view

Returns: The text contained in the view

com.android.monkeyrunner.MonkeyDevice.getViewByAccessibilityIds
Obtains the view with the specified accessibility ids.

Args:
windowId – The window id of the view to retrieve.
accessibility id – The accessibility id of the view to retrieve.
Returns: The view object with the specified id.

com.android.monkeyrunner.MonkeyDevice.getViewById
Obtains the view with the specified id.

Args:
id – The id of the view to retrieve.
Returns: The view object with the specified id.

com.android.monkeyrunner.MonkeyView.getViewClass
Returns the class name of the view

Returns: The class name of the view as a string

com.android.monkeyrunner.MonkeyDevice.getViewIdList
Retrieve the view ids for the current application

Returns: returns nothing.

com.android.monkeyrunner.MonkeyDevice.getViewsByText
Obtains a list of views that contain the specified text.

Args:
text – The text to search for
Returns: A list of view objects that contain the specified text.

com.android.monkeyrunner.MonkeyRect.getWidth
Returns the width of the rectangle

Returns: The width of the rectangle as an integer

com.android.monkeyrunner.MonkeyRunner.help
Format and display the API reference for MonkeyRunner.

Args:
format – The desired format for the output, either ‘text’ for plain text or ‘html’ for HTML markup.
Returns: A string containing the help text in the desired format.

com.android.monkeyrunner.MonkeyRunner.input
Display a dialog that accepts input. The dialog is ,modal, so the script stops until the user clicks one of the two dialog buttons. To enter a value, the user enters the value and clicks the ‘OK’ button. To quit the dialog without entering a value, the user clicks the ‘Cancel’ button. Use the supplied arguments for this method to customize the text for these buttons.

Args:
message – The prompt message to display in the dialog.
initialValue – The initial value to supply to the user. The default is an empty string)
title – The dialog’s title. The default is ‘Input’
okTitle – The text to use in the dialog’s confirmation button. The default is ‘OK’.The text to use in the dialog’s ‘cancel’ button. The default is ‘Cancel’.
cancelTitle –
Returns: The test entered by the user, or None if the user canceled the input;

com.android.monkeyrunner.MonkeyDevice.installPackage
Installs the specified Android package (.apk file) onto the device. If the package already exists on the device, it is replaced.

Args:
path – The package’s path and filename on the host filesystem.
Returns: True if the install succeeded

com.android.monkeyrunner.MonkeyDevice.instrument
Run the specified package with instrumentation and return the output it generates. Use this to run a test package using InstrumentationTestRunner.

Args:
className – The class to run with instrumentation. The format is packagename/classname. Use packagename to specify the Android package to run, and classname to specify the class to run within that package. For test packages, this is usually testpackagename/InstrumentationTestRunner
args – A map of strings to objects containing the arguments to pass to this instrumentation (default value is None).
Returns: A map of strings to objects for the output from the package. For a test package, contains a single key-value pair: the key is ‘stream’ and the value is a string containing the test output.

com.android.monkeyrunner.MonkeyRunner.loadImageFromFile
Loads a MonkeyImage from a file.

Args:
path – The path to the file to load.  This file path is in terms of the computer running MonkeyRunner and not a path on the Android Device.
Returns: A new MonkeyImage representing the specified file

com.android.monkeyrunner.MonkeyDevice.press
Send a key event to the specified key

Args:
name – the keycode of the key to press (see android.view.KeyEvent)
type – touch event type as returned by TouchPressType(). To simulate typing a key, send DOWN_AND_UP
Returns: returns nothing.

com.android.monkeyrunner.MonkeyDevice.reboot
Reboots the specified device into a specified bootloader.

Args:
into – the bootloader to reboot into: bootloader, recovery, or None
Returns: returns nothing.

com.android.monkeyrunner.MonkeyDevice.removePackage
Deletes the specified package from the device, including its associated data and cache.

Args:
package – The name of the package to delete.
Returns: True if remove succeeded

com.android.monkeyrunner.MonkeyImage.sameAs
Compare this MonkeyImage object to aother MonkeyImage object.

Args:
other – The other MonkeyImage object.
percent – A float in the range 0.0 to 1.0, indicating the percentage of pixels that need to be the same for the method to return ‘true’. Defaults to 1.0.
Returns: boolean ‘true’ if the two objects contain the same image.

com.android.monkeyrunner.MonkeyView.setFocused
Sets the focused status of the view

Args:
focused – The boolean value to set focused to
Returns: returns nothing.

com.android.monkeyrunner.MonkeyView.setSelected
Sets the selected status of the view

Args:
selected – The boolean value to set selected to
Returns: returns nothing.

com.android.monkeyrunner.MonkeyDevice.shell
Executes an adb shell command and returns the result, if any.

Args:
cmd – The adb shell command to execute.
Returns: The output from the command.

com.android.monkeyrunner.MonkeyRunner.sleep
Pause the currently running program for the specified number of seconds.

Args:
seconds – The number of seconds to pause.
Returns: returns nothing.

com.android.monkeyrunner.MonkeyDevice.startActivity
Starts an Activity on the device by sending an Intent constructed from the specified parameters.

Args:
uri – The URI for the Intent.
action – The action for the Intent.
data – The data URI for the Intent
mimetype – The mime type for the Intent.
categories – A Python iterable containing the category names for the Intent.
extras – A dictionary of extras to add to the Intent. Types of these extras are inferred from the python types of the values.
component – The component of the Intent.
flags – An iterable of flags for the Intent.All arguments are optional. The default value for each argument is null.(see android.content.Intent)
Returns: returns nothing.

com.android.monkeyrunner.MonkeyDevice.takeSnapshot
Gets the device’s screen buffer, yielding a screen capture of the entire display.

Returns: A MonkeyImage object (a bitmap wrapper)

com.android.monkeyrunner.MonkeyDevice.touch
Sends a touch event at the specified location

Args:
x – x coordinate in pixels
y – y coordinate in pixels
type – touch event type as returned by TouchPressType()
Returns: returns nothing.

com.android.monkeyrunner.MonkeyDevice.type
Types the specified string on the keyboard. This is equivalent to calling press(keycode,DOWN_AND_UP) for each character in the string.

Args:
message – The string to send to the keyboard.
Returns: returns nothing.

com.android.monkeyrunner.MonkeyRunner.waitForConnection
Waits for the workstation to connect to the device.

Args:
timeout – The timeout in seconds to wait. The default is to wait indefinitely.
deviceId – A regular expression that specifies the device name. See the documentation for ‘adb’ in the Developer Guide to learn more about device names.
Returns: A ChimpDevice object representing the connected device.

com.android.monkeyrunner.MonkeyDevice.wake
Wake up the screen on the device

Returns: returns nothing.

com.android.monkeyrunner.MonkeyImage.writeToFile
Write the MonkeyImage to a file.  If no format is specified, this method guesses the output format based on the extension of the provided file extension. If it is unable to guess the format, it uses PNG.

Args:
path – The output filename, optionally including its path
format – The destination format (for example, ‘png’ for  Portable Network Graphics format.
Returns: boolean true if writing succeeded.

Help.py (monkeyrunner)

Not my file  just a copy of what I found (file needs to be saved as help.py)

#!/usr/bin/env monkeyrunner
# Copyright 2010, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the “License”);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an “AS IS” BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from com.android.monkeyrunner import MonkeyRunner as mr

import os
import sys

supported_formats = [‘html’, ‘text’, ‘sdk-docs’]

if len(sys.argv) != 3:
print ‘help.py: format output’
sys.exit(1)

(format, saveto_path) = sys.argv[1:]

if not format.lower() in supported_formats:
print ‘format %s is not a supported format’ % format
sys.exit(2)

output = mr.help(format=format)
if not output:
print ‘Error generating help format’
sys.exit(3)

dirname = os.path.dirname(saveto_path)
try:
os.makedirs(dirname)
except:
print ‘oops’
pass # It already existed

fp = open(saveto_path, ‘w’)
fp.write(output)
fp.close()

sys.exit(0)

Monkey Runner (help.py and API Referrence)

Running on Windows 7

So trying something more robust now for test automation for Android (while trying to avoid 3rd party apps)  This time Monkey Runner (not the same as Monkey) – something also included in the Android SDK. This takes us into a more robust scripting language Python (which I haven’t played with much before, but there is always google)

Monkey Runner

One problem I ran into is generating the API Reference.

Per the Android Website I should run this:

monkeyrunner help.py <format> <outfile>

Which translates to this

monkeyrunner help.py text help.txt

Help.txt just being the name of the file where I wanted to dump the information.

First problem, I didn’t have help.py.

I finally found it online here: http://source-android.frandroid.com/sdk/monkeyrunner/scripts/help.py

Second Problem

But when I tried to run it, I kept saying:  “oops”

After some trouble shooting, I found that it kept trying to “create” the directory that “monkeyrunner” was already installed in an running. – Lame

So I ended up changing this line in help.py

os.makedirs(dirname)

To:

fo = open(saveto_file, “w”)

I also printed out the name and status of the file (though not needed) and changed a copy other lines from using “fp” to “fo”

#Print statements not need but I added them for me
print ‘Name of the file: ‘, fo.name
print ‘Closed or not   : ‘, fo.closed
print ‘Opening mode    : ‘, fo.mode
print ‘Softspace flag  : ‘, fo.softspace

# Changed fp to fo
fo = open(saveto_path, ‘w’)
fo.write(output)
fo.close()

And I included the full path in the file name (though there is probably a better way to do that if you are a python guru.

monkeyrunner help.py text C:\MyPath\help.txt

But it worked and I got the API reference, while I will also post and I will upload a copy of the help.py file