Monday, November 25, 2013

Android Continuous Integration Guides: Ebook I



 This book helps you explored Continuous Integration in practice providing valuable information to start applying it soon to your Android projects.

Employs Ant to automate the building process, git to create a simple version control system repository to store our source code and manage the changes, and finally installs and configures Jenkins as the Continuous Integration of choice. In this journey we detail the creation of jobs for automating the building process of TemperatureConverter, its dependency library LocalViewServer and its tests and we emphasized on the relationship between the projects.

Finally, we analyze a way of getting XML results from Android tests and implement this to obtain an attractive interface to monitor the running of tests, their results, and the existing trends and using and showing EMMA code coverage reports.

This will save you precious time and experimentation leading you through a step-by-step guide.

Visit Google Play Books to find more.

Thursday, October 10, 2013

AndroidViewClient/culebra version 4.6.0: now 100% pure python

AndroidViewClient/culebra v4.6.0 has been released bringing major improvements closing the gap with the existing APIs. This is demonstrated by the example scripts migrated to use AdbClient now, instead of MonkeyDevice.
monkeyrunner seems much farther in the rearview mirror.

changelog

  • AdbClient: Added isLocked() method to check if screen is locked
  • Fixed #55: drag doesn't work for old Android versions
  • Removed sys.path manipulation not needed for python
  • Read ANDROID_ADB_SERVER_PORT environment variable to set adb PORT. This variable is set by Jenkins Android Emulator plugin.
  • Merge pull request #56 from knorrium/clean-whitespaces
  • Check for sys.executable that may be not available on Windows
  • Examples modified to use python
  • Marked jar file creation as deprecated
  • Improved UTF-8 treatment in messages
  • AdbClient.startActivity() raises exception on errors
  • Warns if modules are imported using 'monkeyrunner'
  • Added image comparison
  • Decode used only on python's 8-bit strings
  • Restored obtainAdbPath() used for android API <= 16
  • Trap exception generated by integer division by zero in takeSnapshot()
  • Fixed famebuffer exception



Monday, September 09, 2013

AndroidViewClient/culebra takeSnapshot() improvements

The latest release of AndroidViewClient/culebra v.4.2.1 includes now the implementation of AdbClient.takeSnapshot(), replacing MonkeyDevice.takeSnapshot() used in previous releases.

Starting from AndroidViewClient v4.0.0, monkeyrunner was ditched in favor of plain good old python. This change brought massive speed improvements in running tests as it was described in AndroidViewClient/culebra version 4.0.0: now 100% pure python, and takeSnapshot() is not an exception.

In order to measure the improvement, 2 scripts were added to the examples, one taking a screenshot using MonkeyDevice.takeSnapshot() and the orher using the alternative AdbClient.takeSnapshot(). As with other functionality, the API is maintained so changes to existing scripts are unnecessary or just minimum.


screenshot-monkeyrunner.py

The script taking the screenshot of the device or emulator using monkeyrunner.


#! /usr/bin/env monkeyrunner
'''
Copyright (C) 2012  Diego Torres Milano
Created on Set 5, 2013

@author: diego
'''


import sys
import os

from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice

if len(sys.argv) < 2:
    print >> sys.stderr, "usage: %s filename.png" % sys.argv[0]
    sys.exit(1)

filename = sys.argv.pop(1)
device = MonkeyRunner.waitForConnection()
device.takeSnapshot().writeToFile(filename, 'PNG')

screenshot.py

The script taking the screenshot of the device or emulator using python.


#! /usr/bin/env python
'''
Copyright (C) 2012  Diego Torres Milano
Created on Aug 31, 2013

@author: diego
'''


import sys
import os

from com.dtmilano.android.viewclient import ViewClient

if len(sys.argv) < 2:
    sys.exit("usage: %s filename.png [serialno]" % sys.argv[0])

filename = sys.argv.pop(1)
device, serialno = ViewClient.connectToDeviceOrExit(verbose=False)
device.takeSnapshot().save(filename, 'PNG')

results

Both scripts were run to take the screenshot of a Nexus 4 (android api-18) home screen.

As you may have been anticipating, the python script run much faster and this is illustrated in the following chart.



Something to take into account is that both script are almost the same, except for some improvements that are supported only by AndroidViewClient, like the possibility of requesting a verbose connection or specifying the device serial number in the command line.
Also, notice that instead of writeToFile() like MonkeyImage does, save() is used. This is because AdbClient.takeSnapshot() returns a real PIL Image and not a wrapper.

Hope you enjoyed the changes.
If you have any question or comments just post it on Google+ or Stackoverflow.

Tuesday, August 27, 2013

AndroidViewClient/culebra version 4.0.0: now 100% pure python

AndroidViewClient/culebra v4.0.0 has been released bringing major improvements and an incredible speed gain by removing the dependency on monkeyrunner and now using python as the interpreter.

I have been thinking about this change for a very long time but never had the time to do it. In one way or another I found workaround after workaround for monkeyrunner and ChimpChat problems. If monkeyrunner was not detecting that the device was not actually connected, AndroidViewClient was forcing a wake() after waitForConnection() returns to verify that everything was right or catching the Exception and showing a more meaningful message (code). If the connection attempt didn't time out and hangs AndroidViewClient was also providing a workaround (code).
Lately, on some Android devices, uiautomator is killed before finishing and the Killed message is also included in the output, and then AndroidViewClient also provided a workaround (code).
I could name several more, but I think you got the idea.

However, it wasn't until the introduction of this bug:

Issue 58912:UiAutomator and UiAutomation-based tests fail to run when chimpchat connection is present on 4.3

when things were really screaming for a long term solution and not just another workaround.

Then, I took adbclient module I have been developing some time ago to be able to run some stability tests (did I mention ChimpChat was not stable enough to run them?), modify it a bit and now AndroidViewClient/culebra and dump are not  dependant on monkeyrunner or ChimpChat and can use any compatible python interpreter.

The inclusion of adbclient also brought some tremendous speed improvement, something you would thank if you have to run hundreds or thousands of tests.

These charts demonstrates the improvements:



This is just the beginning. Stay tuned and you will see more improvements coming.

Friday, August 09, 2013

AndroidViewClient/culebra version 3.2.0 released

The focus of this new release is to improve UTF-8 support.
Latest AndroidViewClient/culebra release (v3.2.0) can now be found at https://github.com/dtmilano/AndroidViewClient/releases/tag/v3.2.0

These are the release notes:

  • Added UTF-8 support for str* methods
  • Explicit error message when received XML is not valid
  • Added Chinese text tests



Wednesday, July 31, 2013

Android 4.3 (Jellybean) update breaks some things

It is quite annoying.
I guess this should not happen for a major release.

UiAutomator is kind of broken. I've found this problem on a Nexus 4 and also on emulator, so it seems generic. Now when Chimpchat opens a connection (i.e. monkeyrunner) and you try to run uiautomator from a different adb shell you'll get

07-30 23:49:51.821: D/AndroidRuntime(2951): >>>>>> AndroidRuntime START com.android.internal.os.RuntimeInit <<<<<<
07-30 23:49:51.821: D/AndroidRuntime(2951): CheckJNI is OFF
07-30 23:49:51.831: D/dalvikvm(2951): Trying to load lib libjavacore.so 0x0
07-30 23:49:51.841: D/dalvikvm(2951): Added shared lib libjavacore.so 0x0
07-30 23:49:51.841: D/dalvikvm(2951): Trying to load lib libnativehelper.so 0x0
07-30 23:49:51.841: D/dalvikvm(2951): Added shared lib libnativehelper.so 0x0
07-30 23:49:51.981: D/AndroidRuntime(2951): Calling main entry com.android.commands.uiautomator.Launcher
07-30 23:49:51.991: D/AndroidRuntime(2951): Shutting down VM
07-30 23:49:51.991: W/dalvikvm(2951): threadid=1: thread exiting with uncaught exception (group=0x415b9700)
07-30 23:49:51.991: D/dalvikvm(2951): Note: class Landroid/app/ActivityManagerNative; has 163 unimplemented (abstract) methods
07-30 23:49:51.991: E/JavaBinder(2951): Unknown binder error code. 0xfffffff7
07-30 23:49:51.991: E/ServiceManager(2951): error in getService
07-30 23:49:51.991: E/ServiceManager(2951): android.os.RemoteException: Unknown binder error code. 0xfffffff7
07-30 23:49:51.991: E/ServiceManager(2951): at android.os.BinderProxy.transact(Native Method)
07-30 23:49:51.991: E/ServiceManager(2951): at android.os.ServiceManagerProxy.getService(ServiceManagerNative.java:123)
07-30 23:49:51.991: E/ServiceManager(2951): at android.os.ServiceManager.getService(ServiceManager.java:55)
07-30 23:49:51.991: E/ServiceManager(2951): at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:1893)
07-30 23:49:51.991: E/ServiceManager(2951): at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:1891)
07-30 23:49:51.991: E/ServiceManager(2951): at android.util.Singleton.get(Singleton.java:34)
07-30 23:49:51.991: E/ServiceManager(2951): at android.app.ActivityManagerNative.getDefault(ActivityManagerNative.java:73)
07-30 23:49:51.991: E/ServiceManager(2951): at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:76)
07-30 23:49:51.991: E/ServiceManager(2951): at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
07-30 23:49:51.991: E/ServiceManager(2951): at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
07-30 23:49:51.991: E/ServiceManager(2951): at dalvik.system.NativeStart.main(Native Method)
07-30 23:49:51.991: I/Process(2951): Sending signal. PID: 2951 SIG: 9
07-30 23:49:51.991: E/AndroidRuntime(2951): *** FATAL EXCEPTION IN SYSTEM PROCESS: main
07-30 23:49:51.991: E/AndroidRuntime(2951): java.lang.IllegalStateException: UiAutomationService android.accessibilityservice.IAccessibilityServiceClient$Stub$Proxy@427adc60already registered!
07-30 23:49:51.991: E/AndroidRuntime(2951): at android.os.Parcel.readException(Parcel.java:1439)
07-30 23:49:51.991: E/AndroidRuntime(2951): at android.os.Parcel.readException(Parcel.java:1385)
07-30 23:49:51.991: E/AndroidRuntime(2951): at android.view.accessibility.IAccessibilityManager$Stub$Proxy.registerUiTestAutomationService(IAccessibilityManager.java:342)
07-30 23:49:51.991: E/AndroidRuntime(2951): at android.app.UiAutomationConnection.registerUiTestAutomationServiceLocked(UiAutomationConnection.java:173)
07-30 23:49:51.991: E/AndroidRuntime(2951): at android.app.UiAutomationConnection.connect(UiAutomationConnection.java:72)
07-30 23:49:51.991: E/AndroidRuntime(2951): at android.app.UiAutomation.connect(UiAutomation.java:188)
07-30 23:49:51.991: E/AndroidRuntime(2951): at com.android.uiautomator.core.UiAutomationShellWrapper.connect(UiAutomationShellWrapper.java:32)
07-30 23:49:51.991: E/AndroidRuntime(2951): at com.android.commands.uiautomator.DumpCommand.run(DumpCommand.java:74)
07-30 23:49:51.991: E/AndroidRuntime(2951): at com.android.commands.uiautomator.Launcher.main(Launcher.java:83)
07-30 23:49:51.991: E/AndroidRuntime(2951): at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
07-30 23:49:51.991: E/AndroidRuntime(2951): at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:235)
07-30 23:49:51.991: E/AndroidRuntime(2951): at dalvik.system.NativeStart.main(Native Method)
07-30 23:49:51.991: E/AndroidRuntime(2951): Error reporting crash
07-30 23:49:51.991: E/AndroidRuntime(2951): java.lang.NullPointerException
07-30 23:49:51.991: E/AndroidRuntime(2951): at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:76)
07-30 23:49:51.991: E/AndroidRuntime(2951): at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
07-30 23:49:51.991: E/AndroidRuntime(2951): at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
07-30 23:49:51.991: E/AndroidRuntime(2951): at dalvik.system.NativeStart.main(Native Method)

This was perfectly valid and correct on Android 4.2.x. It still requires some investigation, but I wanted to post it here just in case you find the same, at least you won't feel alone.

UPDATE: 2013-AUG-27:
AndroidViewClient/culebra version 4.0.0: now 100% pure python describes a solution for this problem

Tuesday, July 09, 2013

AndroidViewClient/culebra version 2.3.25 released

Github recently introduced some new features to its release system. There are several improvements. Though it was possible to tag versions before, and AndroidViewClient/culebra has been doing it for a while, now the release system is a first class citizen and can include binary files (solving one problem that was solved using Google Drive in previous releases).

Latest AndroidViewClient/culebra release (v2.3.25) can now be found at https://github.com/dtmilano/AndroidViewClient/releases/v2.3.25

These are the release notes:
Added methods to calculate dump distances
  • Version 2.3.25
  • Added Hamming distance
  • Added Levenshtein distance
  • Added View.__microStr__()
  • Traverse refactoring
  • Improved docs

The binary distribution and documentation can also be downloaded from the release.
More on these later.

Saturday, May 25, 2013

monkeyrunner: ImportError: No module named re

If you have recently upgraded to Android SDK Tools Rev. 22 you may have sadly discovered that monkeyrunner is broken because the wrong jython library was included in the build.
This is not due to the upgrade to jython 2.5.3 but to an incorrect library used, that is jython instead of jython-standalone.

It seems that the move to a gradle based build system is causing some trouble. Fortunately, it has been fixed already by https://android-review.googlesource.com/#/c/59173/1 which is now merged, so by the time Android SDK Tools Rev. 22.0.1 is out the problem would be in the rear-view mirror.

In the meantime, you can apply this simple workaround:

  1. Download jython-standalone-2.5.3.jar
  2. Save /tools/lib/jython-2.5.3.jar as jython-2.5.3.jar.ORI (just in case you need it)
  3. Symlink (or copy, if your OS does not support symlinks ;-) jython-standalone-2.5.3.jar to jython-2.5.3.jar
After applying these simple steps monkeyrunner, androidviewclient, dump and culebra will work as before.

Friday, May 17, 2013

AndroidViewClient documentation

AndroidViewClient documentation has been updated and now covers most of the public classes and method.

The documentation is generated by epydoc, which also generates some UML class diagrams.

The objective of this documentation is to allow script development without having to have AndroidViewClient sources open.

Sunday, April 28, 2013

AndroidViewClient @ stackoverflow

AndroidViewClient is constantly increasing its popularity and the number of questions I've been receiving through the open channels is very high and sometimes they may be left unanswered or lost.

Fortunately, the tag androidviewclient was added to stackoverflow and this will greatly improve the follow up of any question or problem.

Visit http://stackoverflow.com/questions/tagged/androidviewclient for more details.

Sunday, March 31, 2013

AndroidViewClient: dump.py explained


dump.py is an extremely valuable tool if you are developing tests or scripts based on AndroidViewClient.
It was created as a simple example to demonstrate AndroidViewClient features but it became something more than that. Nevertheless, the intention is to keep it simple enough to be used as an example, so some extra features will be provided by different tools.
As its name indicates, the main function is to dump the content of the screen present on a device or emulator at any given time, but instead of providing it as a bitmap the result of running dump.py is the logical representation of the screen as a tree that can be also printed in textual form.
A detailed description of this important tool has been made available in AndroidViewClient's wiki at: https://github.com/dtmilano/AndroidViewClient/wiki/dump.py
Dont hesitate to send your comments and questions to AndroidViewClient's Google+ page where they can be easily follow up.

Wednesday, January 16, 2013

android select device

A new version of the script android-select-device has been made available, now as a gist.
Its usage has been described in a previous post: selecting adb device.
Basically, when you are dealing with several devices or emulators, instead of specifying the serial number on every command line you can do something like

$ adb $(android-select-device) shell
1) 02783201431feeee device 3) emulator-5554
2) 3832380FA5F30000 device 4) emulator-5556
Select the device to use, to quit: 1
uid=0 gid=0@android:/ #

I hope you find it useful.