Luke Ashe-Browne Open source, web technology and feeble attempts at eloquence

22Jul/100

Testing mobile web apps with Android SDK

Android boot splash screen

I've recently been working on a CRM web application with a mobile layout, to work on brands of phone in use by sales representatives of a food wholesalers. So I thought I'd share my experience using the Android SDK emulator to test mobile layouts.

So what's the deal? When building a web app, you are often required to test the resulting layouts of your site on multiple browsers, the usual battery is IE 6 through 8, Firefox 2.x and 3.x, Safari on windows and an Apple product if you can, Google Chrome, and Opera. Well you don't have to, but I like to test on Opera as i think it is a great browser with a forward looking influence on the browser market, while still being different enough to be awkward to support.

In this case we are working on mobile layouts, so what are the platforms we have to worry about?  iPhone, Blackberry, Symbian, Android and possibly Windows mobile or CE. iPhone's run on a version safari, there is also the possible need of Opera support, but we will not cover that here for now.  Android uses a browser based on webkit, so it is very similar to the mobile safari, sans some of the apple specific animation capability.

So why setup an emulator to test with?

Testing wouldn't be too hard for me if I deployed to the live server or even an interim testing hosting setup that was live on the internet, then my HTC Desire or an actual iPhone would be fine, but before that, as I code on my local setup, I need an emulator that can hit my local IP for the virtualhost i have set up for the project.

Emulators! The iPhone as there is no mobile emulator I could use on linux, and in typical closed Apple form, there is only one way to test iPhone layouts without a phone, and that's with their SDK which comes with an emulator that only runs on Mac.

The android SDK on the other hand, works on everything, and also comes with an emulator. So I will outline the setup of setting up the android sdk to use the emulator.

NOTE:
One thing that has come up in research to this project is the Phone-Gap project, an open source cross mobile platform app development framework, which allows mobile developers to code in html, css, javascript and ajax, while also using html5 features to access phone specific features beyond what's usually available to the browser,  like video streaming, audio capture, GPS location and so on. It also comes with a phone browser emulator, but I'm not yet sure of it's accuracy in emulating iPhone browser behaviours. I had trouble getting it to hang onto a session cookie and hence was stuck at the login screen of my app.

My Project

For the sake of technical detail, for the project I'm using, Cakphp - 1.3.3, Zend Framework libraries, jquery and jqtouch.

Requiring different layouts as per a user-agent check is the simplest and most direct solution I can see for now. In this case, CakePHP offers a simple solution in it's isMobile() method in the RequestHanlder class. This method just checks the user-agent headers in a request, which is nice as this can also be run through firefox with the modify headers plugin. run the emulator we will be discussing next, and tail the apache access logs of your local apache instance then hit your local apache instance with the browser from the emulator. Copy the headers from the tail'd log and you have what you need to set in firefox's headers.

Otherwise you can just add an item in cakephp's app_controller beforeFilter method (where all evil acts are commited) to the mobileUA array.

$this->RequestHandler->mobileUA[]='Chrome';

In this example i use Chrome, this works for both the open source Chromium on Linux and Google-Chrome. I haven't found a simple way to differentiate them in this use case.

Now on to the testing harness.

Testing Tools

In the case of firefox, or chromium/google-chrome, it's very simple. There are extensions for both FF and Chrome to do window resizing and firefox can spoof the headers for the User-Agent data. In Chrome/Chromium's case, there is no API available to extension developers as of this writing to allow overriding of the User-Agent header beyond what javascript would be able to read, so apache/php can't be fooled this way.

I wanted to create a cross platform web app layout for  iPhone, Android and hopefully (testing to be worked out) Blackberry. Now my normal development rig is an Ubuntu powered Dell d630 laptop, so I can't run the iPhone SDK and emulator. News is around on the MobiOne iphone emulator/sdk kit for windows, but until I get a chance to see if that'll run on wine, I'm at a disadvantage. In the mean time however, I do have a HTC Desire and the Android SDK is freely and easily available.

I decided against using any eclipse setup as is common with the android SDK community, mostly as I'm not developing a java app just now, and I find eclipse to be a nightmarishly over complex mess. So just sticking to the bare tools available on the command line and doing all my coding in vim, i can still make use of the AVD manager and android emaulator bundled in the SDK.

Setting up the Setting up the SDK.

It's dead simple really. Just go to the android developer site, download the i386 .tar.gz for linux(even if your on 64bit, I am), unpack to a location (I used the Downloads directory in my home directory) and run:

/path/to/android-sdk-linux_86/tools/android

This will run the android sdk console and AVD manager where you can manage your installed packages, your virtual android images, settings and so on.

Android SDK and AVD manager
Android SDK and AVD manager

The first thing you want to do is select the Available Packages area and download the SDK's for Android versions you want. I downloaded the latest at the time of writing, android 2.2 (froyo), and android 2.1 as that is what runs on my HTC Desire.

Create a new Virtual Device
Create a new Virtual Device

Once they are installed, create a new image in the Virtual Devices area. In case you're wondering, AVD stands for Android Virtual Device. I chose to create a 2.1 target for my image, as I wanted to match the build on my phone to what I was working with.

If you want to you can use the command line to create the new image also, you can use the "android" tool in the /tools/ directory to manage AVD's as well as run the SDK console GUI.

For quick help on the android tool and it's options, from the tools/ directory, just run ./android -help  This will show you a thorough list of command line switches and options.

Once you have created the image, you want to boot it up, from the tools directory run:

./emulator -avd nameofimageyourcreated -partition-size 128

We set the -partition-size switch to help with the next step, which is to write the hosts file on to the image. If you don't set the partition size switch you will likely receive an insufficient space error when you try to push a file back onto the image. Unfortunately I haven't found a simple way to set this permanently, or to get files i push to the emulator image to be stored permenantly between emulator runs. Every boot the hosts file is blank in my experience (but if anyone knows how, please leave a comment).

The boot up of the emulator may take a minute so have patients, it will display a black screen showing a simple text "A N D R O I D"  followed by the animated splash android screen as below:

Android boot splash screen

After the Android boot sequence is finished, you need to remount the partition into read-write mode, simple to do.

./adb remount

It should give you a message indicating success,

tools$ ./adb remount
* daemon not running. starting it now *
* daemon started successfully *
remount succeeded
tools$./

Finally, you should setup a hosts file to write to the image. In my example, my laptops ip address is 192.168.0.123, I have a virtual domain setup on my local apache instance for the project of local.clientdomain.com. so your hosts file should look like this

127.0.0.1    localhost
192.168.0.123    local.clientdomain.com

The default android hosts file is just the first line anyway, so no fear in replacing it. Save the above file somewhere handy, I simply created a hostsfiles directory in my android_sdk directory, so in my case the command I run to load the hosts file into the emulator is:

./adb push ../hostsfiles/hosts /system/etc/

This will load the file into the emulator int eh /system/etc/ directory. From reading online I know the /etc/hosts file on the android 2.1 system is symlinked to /system/etc/hosts  so this will result in the /etc/hosts file being the file we want.

Finally we can launch the browser in the emulator and hit http://local.clientdomain.com and we will be greeted with our projects landing page. If you had launched the browser in the emulator before pushing the hosts file, you may experience a delay in the browser registereing the domain.

So that is all there is too it, if you have managed to read through this uneccissarily long explanation, good on you, and I hope that some of this is useful to you. In the near future, I will be posting on my experience with jqtouch, and mobile layout coding.