Android Espresso Test Hangs With Indeterminate ProgressBar

I encountered a fun problem today... My Espresso tests started hanging after I added a ProgressDialog into my layout that was visible when the Activity started.

This was the error in the logs:

Could not launch intent Intent { act=android.intent.action.MAIN flg=0x14000000 cmp=co.blah/.ui.activity.MainActivity } within 45 seconds. Perhaps the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen. Or the activity is doing network calls on creation? See the threaddump logs. For your reference the last time the event queue was idle before your activity launch request was 1476277650154 and now the last time the queue went idle was: 1476277650154. If these numbers are the same your activity might be hogging the event queue.

It was only happening on devices running Lollipop (Android 5.0, 5.1) or higher. So Marshmallow (6.0) and Nougat (7.0) as well.

Apparently the indeterminate ProgressBar animation causes Espresso to think things are still happening. And it just waits. And waits. Until it gets killed after 45 seconds. Great. This happens even though animations are turned off in the developer options.

There were a couple of workarounds I found on the internet, but I felt they had their own issues so I've come up with my own.

Just replace uses of ProgressDialog with TestableIndeterminateProgressBar from this gist (and make sure you have animations disabled in the developer options, which of course you're already doing).

Connecting To ADB Over The Internet

We used to have a physical server in our studio to run our Jenkins continuous integration for our Android projects, but after several machines gave up in quick succession I decided it would be cheaper and less time consuming to set one up in the cloud (we chose Digital Ocean as we already have a few virtual servers there). This means we don't have to worry about hardware failures, our studio internet connection, or backing up (digital ocean can do that for you). One less thing to worry about!

However, this presented us with a challenge... We like to run some of our tests (connectedAndroidTest) on real devices, and you can't really plug a usb hub into a 'cloud'.

Solving The Problem

I solved this problem with a Raspberry Pi and an ssh tunnel.


Adb has several parts: a client, a server, and the bit that runs on the Android device.

Essentially, the adb client runs when you type 'adb' on the command line, this then connects to the adb daemon (over a port). The adb daemon runs in the background and is the bit that connects to the devices over usb.

Tunnel Pi

We now have a Pi in our studio that the Android devices are plugged into. The adb daemon runs on this Pi.

Whenever Jenkins wants to use the devices, it opens an ssh tunnel to the Pi, forwarding a port, so Jenkins' adb client can connect to the Pis' adb daemon. Once this port has been forwarded, adb works as normal. It's actually quite simple!


Your local internet connection. It's gotta be fairly good. For example, it works flawlessly on a 30mb connection, but sometimes timed out over a very busy 6mb connection.

Adb isn't available to download for the Pi, so you have to compile it yourself. You have to make sure the adb client and adb daemon are the same versions, otherwise they refuse to talk to each other.

How Do I Set This Up?

For detailed step by step instructions, including compiling adb on the Pi and what to run in your Jenkins job, I've written it up as a Gist...

Read Android App Data Folder Without Root

I'm currently debugging an Android app that has a data directory size that's increasing to several hundred megabytes, not good! It should be only a few kilobytes.

To find out what is going on I needed to see inside the data directory, but this is only possible if the phone is rooted, I don't want to that, so I needed an alternative.

After some browsing I found an github project that converts android backups into a tar (compressed file) format.

I've compiled the jar for you to download, but if you don't want that, you can compile it yourself. Once you've downloaded the jar just run:

adb backup -noapk com.instagram.android
java -jar path/to/abe-all.jar unpack backup.ab backup.tar

Then extract the backup.tar file with your favourite compression utility, and you'll have a whole load of exciting files!

How To Cast Your Android Screen To Mac

I've been doing Android demo meetings for a while by pointing a webcam at a phone and hoping the automatic exposure doesn't go wild half way through, always slightly envious of the iOS simulator that actually almost works, and the wide support for casting or airplay-ing an iPhone screen to your laptop / projector screen (which can then of course be shared very easily via Skype).

Ever since the "cast screen" settings appeared in Android 4.4 Kitkat I've thought that it must be possible to send your screen to a mac, but apparently that only works with a Chromecast, which of course my Mac is not, and nor can it pretend to be.

Well, this evening I have discovered the solution to my problem:

You'll run into a problem if your phone isn't Lollipop (or a rooted KitKat), but if that's the case, maybe buy yourself a nice cheap Moto E for presentations, or get your boss to.

Update 25th August 2015: There's also another way to this, over USB so it's more reliable. Download the Vysor app in Chrome, and connect your device.

Android Design 2014: Dropping iOS Patterns

At the last GDG Brighton I spoke on the difference between designing for iOS and Android.

Here are the slides and a recording of the talk:


For those that remember, it's an updated version of the talk I did a few years ago at Brighton Digital Festival.