Accessing Local Name-Based Virtual Hosts From the Android Emulator

Posted in Android by Dan on January 12th, 2012

To test mobile versions of websites, it is useful to be able to connect to a web server on your local machine from a web browser on an Android emulator without having to expose the web server to the Internet.  You can’t use the normal loop-back IP address of 127.0.0.1 because that refers to the emulated Android device itself.  Instead you have to use 10.0.2.2 to connect to the host machine.

That’s fine if your local web server is serving a single site, but if you are using name-based virtual hosting to serve different sites depending on the host name of the request (with aliases for localhost defined in your machine’s hosts file), then you need to be making requests from the browser using the correct host name, not the IP address.

The Android emulator does not use the host machine’s hosts file for name resolution so attempting to access http://myvirtualhost in the emulator’s browser will not work.  This is because the emulated Android device has its own hosts file, so you have to update this to map the virtual host names to the local machine.

The first step is to start the AVD with an increased partition size otherwise you may get an out of memory error when you try to save the modified hosts file:

  emulator -avd MyAVD -partition-size 128

You then have to remount the system partition so that it is writeable:

  adb remount

Then copy the hosts file from the emulated device to the host machine:

  adb pull /etc/hosts

Edit the hosts file so that it includes mappings for all relevant virtual host names:

127.0.0.1        localhost
10.0.2.2         myvirtualhost1 myvirtualhost2

Then copy the updated file back to the emulated device:

  adb push hosts /etc/hosts

You should then be able to visit http://myvirtualhost1 in the emulator’s browser and see the correct site.

Fixing Disappearing Big Text on Honeycomb Devices

Posted in Android by Dan on October 30th, 2011

I haven’t seen this problem described anywhere else, let alone solved, so this post might prove useful to some desperate future Google searcher.

A couple of weeks ago I updated Rectangular Video Poker to support Honeycomb devices. In doing so I encountered a bizarre bug. The letter ‘J’ refused to display in one particular TextView. Neither the upper case or lower case variant would show, just a gap where the letter should appear. Every other letter in the alphabet displayed correctly. The problem occurred on the 10.1″ Galaxy Tab but not on the Honeycomb emulator or the two HTC phones that I tried.

The problematic TextView had a large font size (86dp) set for xlarge screens because it is used as a banner that displays the win/lose message at the end of a hand. Eventually I discovered that if I dropped the font size to 79dp the letter ‘J’ would reappear. In the absence of any explanation for this odd behaviour, making the text slightly smaller seemed to be a reasonable workaround. Why was ‘J’ the only letter affected? My best guess is because, in the default Droid Sans font, it is taller than all of the other letters. Unusually, the upper case ‘J’ descends below the baseline. The lower case variant is also taller than all other letters.

With an adequate workaround in place I ignored the issue until the other day when I encountered the same problem porting a different app to Honeycomb. This app uses a large TextView to display a number. The font size is even bigger (a scarcely sensible 142dp) and consequently none of the digits displayed. Again, the problem only manifested itself on the Galaxy Tab.

In this case reducing the font size wasn’t really an option (if anything I want to make it bigger to occupy more of the Tab’s very large screen). I did however establish that I would have to lower the size to 101dp to make the text reappear.

I couldn’t find any references to this issue anywhere online (maybe other developers aren’t as fond of massive text as I am). Eventually, due to lack of better ideas, I speculatively disabled hardware acceleration for the activity in question. Surprisingly this solved the problem. I had been following the advice given at the Android Developer Lab to turn on hardware acceleration unless you have a good reason not to, but I hadn’t realised it was the source of my problem because I hadn’t first tested the app without acceleration.

This is the second scenario I’ve discovered in which I have needed to disable hardware acceleration for an activity. It’s also necessary when you have a WebView with a transparent background.

Droidcon UK Day 2

Posted in Android, JavaScript by Dan on October 7th, 2011

Another day, another early train to London. Following yesterday’s Barcamp, the second and final day of Droidcon UK was for the scheduled presentations. Mark Murphy (a.k.a. @commonsguy/the StackOverflow Android guru) delivered a well received opening keynote (video here) containing several predictions of where the Android ecosystem is heading over the next 3 years.

The first of the inevitable sponsors’ keynotes saw Cisco pitch its enterprise Android tablet, the Cius. It’s a chunky 7-inch device (I’m sure they’d say “rugged”) and it only runs Android 2.2, but it represents a different approach to tablets compared to other Android device manufacturers. The main selling point is that it’s part of a fully integrated enterprise communications platform (VOIP, video-conferencing, etc.) that includes a desk phone docking station for the tablet. Later, in the afternoon, HTC touted its Android APIs for exploiting features specific to HTC tablets, such as the pen input on the HTC Flyer.

The rest of the day provided the opportunity to pick and choose from four streams of presentations. Erik Hellman from Sony Ericsson spoke about how to use hidden APIs in Android. These are features that are publicly available at compile time but explicitly excluded from Google’s documentation (via a Javadoc @hide annotation in the source). The examples were how to write code to access a device’s SMS message store and how to programatically toggle WiFi tethering.

Emlyn Howell from Accenture provided an interesting diversion with his discussion of the challenges of building in-car entertainment systems using Android. The thought of roads full of people playing with touchscreens rather than looking at the road is enough to make me never want to drive again, but apparently this danger is avoided by providing reliable voice control functionality.

One of the things you hope to get from events such as Droidcon is valuable insights that you can go away and apply to your own work. Truthfully, I didn’t really get so much of that from today’s presentations compared to yesterday or the ADL on Monday. However, there was one presentation towards the end of the day that I did find particularly interesting and intend to explore in more detail. James Hugman presented Kirin, a new JavaScript framework for developing cross-platform mobile apps with truly native user interfaces. The UIs are developed using the platform’s standard tools and then bound to the application logic written in JavaScript. This avoids the UI compromises of PhoneGap and Titanium Appcelerator while eliminating the duplication of logic that occurs with a strategy of 100% native apps for each platform.

Droidcon UK Barcamp Round-Up

Posted in Android by Dan on October 6th, 2011

Following on from the Android Developer Lab on Monday, I was in London again today for Day 1 of Droidcon UK. The first day of this two-day event is a Barcamp followed by a Democamp in the evening. This is a round-up of what I experienced in the Barcamp sessions (I didn’t hang around for Democamp, opting instead for an earlier train back to darkest Kent).

I hadn’t attended a Barcamp previously so I wasn’t entirely sure what to expect. In the end there was nothing particularly novel about the format, at least in the sessions I attended. After the initial pitching it was just a series of speakers delivering pre-prepared presentations like at any other conference.

10:20 AM – Terence Eden (InMobi)

I’m interested in finding out how to make money more effectively from ad-supported apps (my limited efforts with AdMob have not exactly been lucrative), and in the pre-presentation pitching session Terence was the only person to offer a monetary incentive to attend his talk (in the form of free InMobi advertising credit). Terence made two key points. Firstly, developers really should make sure that their apps are internationalised. Free apps can generate lots of ad revenue in countries like Japan and Indonesia if they are available in the local language. Secondly, app revenue is recurring. For apps that have a long lifetime, monetising using ads can be better than charging for the app in the long term.

11:00 AM – Ashay Padwal (Vserv)

Another mobile advertising talk. Vserv offers a system whereby ads are tacked onto the beginning and/or end of an app rather than intrusively within the main flow of the app. The technique used to implement this does not require any coding, it’s a modification made directly to the APK file. Vserv also provides mediation services to simplify dealing with multiple ad networks (this is presumably similar to AdWhirl).

11:40 AM – Cyril Mottier (GreenDroid)

I met Cyril and spoke to him briefly at the start of the day. He is the author of the GreenDroid library. I’d been aware of GreenDroid for a while but not had a chance to take a proper look at it. GreenDroid provides an ActionBar implementation for non-Honeycomb devices, a view pager, an asynchronous ImageView and other components for building compelling Android UIs. Cyril’s talk also covered techniques for ensuring that your Android GUI is responsive (e.g. using Handlers/AsyncTasks/IntentServices to perform background processing as appropriate).

12:20 PM – Chetan Padia (TouchType)

Chetan spoke about how the developers at TouchType (makers of SwiftKey) solved the problem of building multiple variants of their software from a single codebase. I was interested to learn about their approach as I have made my own attempts at doing something similar. The TouchType team’s approach is more sophisticated than mine and uses a combination of Ant and Python to manipulate their codebase. Part of this involves Java code generation. Chetan mentioned that TouchType is considering open-sourcing its build tool.

2:00 PM – Joe Moore (Pivotal Labs)

Joe spoke about Cloud To Device Messaging (C2DM). This is something I hadn’t done any reading about previously but I was interested to find out about (just how does the GMail app on my phone notify me of e-mails so promptly?). C2DM’s push messages are in most cases a superior option to polling, assuming that you control the server as well as the Android app (requires Froyo or later).

2:40 PM – Nicolas Klein (DataDroid)

Nicolas is another developer I had a chance to speak to early in the day. He told me about DataDroid and then said he wasn’t going to be giving a talk on it. He did give a talk on it. DataDroid provides a framework for managing data locally on the device and for performing REST web service requests to retrieve remote data.

3:20 PM – Martin ??? & Friedger Müffke

Martin and Friedger spoke about NFC. I don’t have a specific interest in NFC but the other talks at the same time didn’t appeal so I thought I’d listen to this. There was the usual mention of mobile payments and train ticketing, a brief demo of reading an NFC tag using an Android Device and some discussion of the other possibilities for NFC.

4:10 PM – Suzanne Nguyen (Immersion)

Again, I wasn’t especially concerned about haptics at the start of the day but this seemed more interesting than the other talks at the same time and, more importantly, I didn’t have to move from my seat after the previous talk. Suzanne spoke about how, using Immersion’s SDK, you can do more with haptic feedback than just basic buzzes. This is best demonstrated by Immersion’s free app that generates these various stimuli.

4:50 PM – Jouko Kaasila (Bitbar)

Jouko provided an overview of the tools available for testing Android apps. These included the Android SDK’s Monkey and monkeyrunner, Robotium (which is apparently like Selenium but for testing Android apps), Roboelectric (simplifies unit testing of Android apps by allowing code that uses the Android APIs to be run inside the standard JVM), and Bitbar’s own Testdroid.

What I Learned at the London Android Developer Lab

Posted in Android by Dan on October 3rd, 2011

This morning I took a brutally early train to London in order to arrive in time for Google’s Android Developer Lab at 8:30 AM. Developing Honeycomb applications for tablet devices was the primary focus of this gathering (around 30-40 Android developers attended) and Google’s affable developer advocates Nick Butcher and Richard Hyndman were our hosts.

Honeycomb

Honeycomb has been on my radar since it was launched back in February but until today I hadn’t got much further than reading the overviews of what it means for developers (e.g. fragments and the action bar) and briefly playing with the painfully slow emulator.

One reason for my lack of Honeycomb activity is that the usage figures are still very low compared to non-Honeycomb devices (Honeycomb runs on just 1.4% of Android devices according to Google’s most recent figures). Today these devices are all tablets of one type or another but Nick cautioned against developing apps with the mindset that Honeycomb = tablets. The Honeycomb APIs are coming to phones with Ice Cream Sandwich (the next major Android version). ICS is apparently informally known as “Honeyphone” within Google, reflecting its focus on reunifying the two streams of Android by bringing Honeycomb’s innovations to phones.

Of course, some of Honeycomb’s features, such as fragments, are already available on devices running Android 1.6 or later via the Android Compatibility Library. Following on from this, another of Nick’s key points was that, whether you are targeting phones, tablets or both, if you are developing Android apps today and you are not using fragments then you are doing it wrong. Fragments are central to Honeycomb, fragments will be central to Ice Cream Sandwich, and fragments are already available (through the compatibility library) for all Android versions back as far 1.6 (Donut).

Android Market

The topics of the day were not all Honeycomb-specific. Richard provided a lot of useful and interesting information about the Android Market. One of the facts that stood out for me was that 7 of the top 10 highest grossing apps on the Market are not even paid-for apps, they are free apps that incorporate in-app billing. If you haven’t considered the in-app billing model for monetising your apps, you could be missing out.

As part of the Market discussions there was a lady in attendance (whose name escapes me, sorry) from the team responsible for the Android Market publisher console. She was collecting feedback to help guide future improvements. There were a lot of good suggestions made.

Richard also gave us the latest figures for Android device activations. There have now been over 150 million total Android device activations and this is increasing at the astonishing rate of 550k per day.

Porting Apps to Honeycomb

There are two very straightforward things to do first when updating an existing app to run on Honeycomb-powered devices. Both involve minor changes to AndroidManifest.xml. Firstly you should set android:targetSdkVersion to 11 or higher. This declares that your application is Honeycomb-aware and will result in it being given the Honeycomb default holographic theme.

The second thing to do is to turn on hardware-accelerated graphics. You need to test your app after enabling acceleration as there are some scenarios that might be problematic, such as custom drawing code, but for the vast majority of apps it is a free performance boost.

As for the frustrations of the very slow Honeycomb emulator, changes are afoot that will address that. In the meantime, Samsung furnished those developers fortunate enough to be present at the Android Developer Lab with a very agreeable alternative to using the emulator.

Kindle Fire Reignites Amazon’s Android Offering

Posted in Android, Hardware by Dan on September 28th, 2011

As expected, Amazon today launched the Kindle Fire, its own Android-powered 7-inch tablet (available to pre-order ahead of a November 15th release). At just $199 the device is even more aggressively priced than the $250 mooted by TechCrunch a few weeks ago. It’s clear that Amazon’s strategy is not to make lots of money selling the hardware but to use it to sell more e-books, MP3s, apps, films and other digital content. It’s this that makes it significant for Android developers – if things play out how Amazon intends, we should see a big increase in sales on the Amazon Appstore.

It’s striking how Amazon has completely down-played the Android underpinnings of its new machine. The word “Android” appears only once on the product page and only then as part of the name “Amazon Appstore for Android”. The Kindle Fire doesn’t look much like an Android device either. This is not a Google-endorsed, Honeycomb-powered tablet. In fact, according to TechCrunch, it runs a fork of Froyo (Android 2.2). Inevitably this adds to Android fragmentation concerns. It remains to be seen whether Amazon will release an emulator image to enable developers to test for this environment.

For now the Kindle Fire is disappointingly but unsurprisingly a US-only proposition. A wider launch of the Amazon Appstore could be imminent and it seems reasonable to expect that the Kindle Fire might follow sometime in 2012.

First Details of Amazon Android Tablet Emerge

Posted in Android, Hardware by Dan on September 3rd, 2011

In my previous post, I concluded that Amazon’s Appstore for Android was an underwhelming proposition for developers and would probably remain so, at least until Amazon’s mooted Android tablets surfaced. Details of a Kindle-branded 7″ Android tablet have now started to appear, with M.G. Siegler on TechCrunch claiming to have actually used the device. Based on his report, it seems Amazon intends to diverge further from Google’s template than any major Android device manufacturer has done so far (Mark Murphy ponders what this means for developers).

Perhaps the most significant detail is the rumoured price point. At $250 (~£154) it will be half the price of an iPad. This thing is likely to sell. And when it sells, app sales should follow.

I suspect the device will initially be available in the US only as this is Amazon’s usual strategy when launching new products and services, and the Appstore itself is US-only at present.

Here’s hoping that, to ensure app compatibility, Amazon decides to send free development devices to those loyal Android developers who have been with its Appstore since launch.

Amazon Appstore Disappoints

Posted in Android by Dan on August 3rd, 2011

Amazon is taking a bit of flak at the moment over the way its Android Appstore operates. The catalyst for this was a blog posting by Australian app developer Shifty Jelly revealing that, contrary to popular belief (belief informed by Amazon’s own Developer Agreement), Amazon does not make payments to the developers of apps it lists as Free App of the Day. The Developer Agreement requires that Amazon reimburses the developer with 20% of the list price for each app it gives away as a free download. However, in order to be listed as Free App of the Day, Amazon apparently requires the developer to agree to waive this part of the contract and to accept 0% instead.

To be clear, Amazon is not forcing the developer to give the app away for nothing, they can decline the offer, but this behaviour does have the faint whiff of a bait and switch and undermines one of the key reasons I highlighted previously for listing your apps with Amazon. Perhaps this is just another example of the old adage that if something sounds too good to be true, it probably is.

Shifty Jelly’s blog post lists additional complaints that echo other disgruntled developers. The approval time is only a minor annoyance for me. Some degree of delay is inevitable on a curated app store and Amazon’s approval time is comparable to Apple’s. Surrendering control of pricing has been controversial but it is clearly outlined when you sign-up. I was willing to go along with this because I assumed that Amazon’s goals would align with mine (we would both benefit from maximising the revenue from my apps).

More annoying is that Amazon will rewrite your app’s description. In most cases for me this has only involved tweaking a few words but in one instance the description was rewritten from scratch and I found the result pretty infantile. The issue extends beyond the description; the developer has no control over the formatting and content of the product page. It’s clear that some publishers are more equal than others because some apps get a rich treatment while most receive only the most basic listing. I enquired about how to get my page upgraded and didn’t really get an answer except to be told that Amazon doesn’t have the resources to provide the full treatment for all apps. On the plus side, at least when I contact Amazon I eventually get a response. There is no indication that there are any human beings involved in the operation of Google’s Android Market.

All of these complaints would be overlooked if the Amazon Appstore delivered impressive revenue for developers but at the moment it doesn’t. Part of this is due to only serving the US. We can reasonably expect that it will eventually expand to other countries where Amazon has a presence, though when this might happen is anyone’s guess. We can also expect to see a big push when Amazon unveils its own Android tablets. For now though Amazon’s offering to developers is underwhelming.

Update (3rd August 2011): Shifty Jelly is having problems getting Amazon to remove the app:

Shifty Jelly on Twitter

I hope this is just a misunderstanding. It’s terrible PR for Amazon.

Embedding AdMob Adverts in Android ListViews

Posted in Android by Dan on May 9th, 2011

Whilst working on StackAnywhere (a new Android client for Stack Overflow and other Stack Exchange websites), I was trying to figure out how best to incorporate AdMob adverts in the UI so that I could make the app free to download. The stumbling block was that, with some space already taken up by the tabbed navigation, the additional space occupied by the adverts tended to make the user interface very cramped with little room for content. This was particularly problematic in landscape orientation since the adverts are the exact same dimensions as in portrait mode which means they take up proportionally more room vertically whilst wasting space horizontally.

StackAnywhere with an advert in a ListViewSince most of StackAnywhere’s activities feature ListViews, I eventually hit on the idea of embedding the adverts in the lists. This is not an entirely original idea, there are other apps that do something similar, but it has the advantage of displaying the advert prominently while also allowing the user to scroll it off screen and out of their way.

Implementing this solution is reasonably straightforward although there are a couple of minor pitfalls to avoid. The decorator pattern is an ideal approach to use since it allows you to add adverts to an existing list adapter without having to modify the code for that adapter. My naive first attempt fell foul of a ClassCastException when adding the AdView to the list, and I also had some focus issues to resolve. The code below is a simplified version of that used in StackAnywhere. The implementation simply adds one advert to the top of the list. You could easily modify this to show more adverts if you wish. For example, you could show an advert after every 10 items. The code assumes that you are using the new Google AdMob SDK (version 4.0.4 in this instance), rather than the old AdMob SDK.

import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;
 
/**
 * List adapter decorator that inserts adverts into the list.
 * @author Daniel Dyer
 */
public class AdvertisingAdapter extends BaseAdapter
{
    private static final String ADMOB_PUBLISHER_ID = "YOUR_ADMOB_ID_HERE";
 
    private final Activity activity;
    private final BaseAdapter delegate;
 
    public AdvertisingAdapter(Activity activity, BaseAdapter delegate)
    {
        this.activity = activity;
        this.delegate = delegate;
        delegate.registerDataSetObserver(new DataSetObserver()
        {
            @Override
            public void onChanged()
            {
                notifyDataSetChanged();
            }
 
            @Override
            public void onInvalidated()
            {
                notifyDataSetInvalidated();
            }
        });
    }
 
    public int getCount()
    {
        return delegate.getCount() + 1;
    }
 
    public Object getItem(int i)
    {
        return delegate.getItem(i - 1);
    }
 
    public long getItemId(int i)
    {
        return delegate.getItemId(i - 1);
    }
 
    public View getView(int position, View convertView, ViewGroup parent)
    {
        if (position == 0)
        {
            if (convertView instanceof AdView)
            {
                return convertView;
            }
            else
            {
                AdView adView = new AdView(activity, AdSize.BANNER, ADMOB_PUBLISHER_ID);
                // Disable focus for sub-views of the AdView to avoid problems with
                // trackpad navigation of the list.
                for (int i = 0; i < adView.getChildCount(); i++)
                {
                    adView.getChildAt(i).setFocusable(false);
                }
                adView.setFocusable(false);
                // Default layout params have to be converted to ListView compatible
                // params otherwise there will be a ClassCastException.
                float density = activity.getResources().getDisplayMetrics().density;
                int height = Math.round(AdSize.BANNER.getHeight() * density);
                AbsListView.LayoutParams params
                    = new AbsListView.LayoutParams(AbsListView.LayoutParams.FILL_PARENT,
                                                   height);
                adView.setLayoutParams(params);
                adView.loadAd(new AdRequest());
                return adView;
            }
        }
        else
        {
            return delegate.getView(position - 1, convertView, parent);
        }
    }
 
    @Override
    public int getViewTypeCount()
    {
        return delegate.getViewTypeCount() + 1;
    }
 
    @Override
    public int getItemViewType(int position)
    {
        return position == 0 ? delegate.getViewTypeCount()
                             : delegate.getItemViewType(position - 1);
    }
 
    @Override
    public boolean areAllItemsEnabled()
    {
        return false;
    }
 
    @Override
    public boolean isEnabled(int position)
    {
        return position != 0 && delegate.isEnabled(position - 1);
    }
}

Scrolling Tabs in Android

Posted in Android by Dan on April 18th, 2011

Perhaps this is obvious but it wasn’t immediately clear to me so maybe it’s worth documenting for the benefit of future Google searchers. If you use a TabActivity in an Android application you can probably fit four or maybe five tabs on a standard screen in portrait orientation before things become too cramped. To display more tabs than this and still be able to read the text on each it would be ideal to have a scrolling tab widget like many UI toolkits do. But how can you do this in an Android app?

Reading the patchy Android API documentation is rarely an illuminating experience at the best of times and it doesn’t help in this instance either because the possibility of scrolling tabs is not even mentioned in the entries for TabHost and TabWidget. In the absence of any better ideas you might speculatively attempt to wrap the TabWidget in a ScrollView. Don’t bother, it won’t do anything, ScrollView only provides vertical scrolling.

Android scrollable tabsIf, like me, you thought that ScrollView was the last word in scrolling Android widgets, you may have failed to notice android.widget.HorizontalScrollView. The name fails to conceal what this class is about. It’s the solution to your non-scrolling tab woes.

Wrap your TabWidget with a HorizontalScrollView and the tab set will be able to expand beyond the width of the screen and the user can drag the tabs left and right as required:

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@android:id/tabhost"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent">
  <LinearLayout android:orientation="vertical"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
    <HorizontalScrollView android:layout_width="fill_parent"
                          android:layout_height="wrap_content"
                          android:fillViewport="true"
                          android:scrollbars="none">
      <TabWidget android:id="@android:id/tabs"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"/>
    </HorizontalScrollView>
    <FrameLayout android:id="@android:id/tabcontent"
                 android:layout_width="fill_parent"
                 android:layout_height="fill_parent" />
  </LinearLayout>
</TabHost>

Set android:fillViewport to true to ensure that the tabs stretch the full width like they would without a scroller and set android:scrollbars to none to avoid having a scrollbar displayed between the tabs and the content. The scrollable tabs will be rendered with faded edges on the right and/or left depending on which direction you can scroll (see image above).

« Older Posts