Fauxboto - Amazon's Holo typeface bug on Kindle Fire#AndroidDev
One of the most welcome but least heralded changes introduced in Android 4.0 was the requirement that hardware partners do not modify any part of the Holo themes in order to pass the Google Compatibility Test Suite (CTS). For the first time, Android developers building against API 14 or above had a base theme that they could be sure had 100% visual consistency across devices from different OEMs. Of course, no such requirement applies to manufacturers who have no interest in bringing the Google Play Store or other Google specific services to their Android based devices.
Amazon have recently refreshed their Kindle line with a 2nd generation range of Kindle Fire tablets running Android 4.0.3 and they have been made available outside of the US for the first time. Kindle Fire represents an interesting new opportunity for Android developers. Having a strong, well supported downstream implementation of Android is also great for the platform itself.
In preparing to submit an app to the Amazon app store for distribution, I deployed it onto my brand new Kindle Fire HD 7" tablet for testing. The app worked great, but something was visually quite wrong:http://i.imgur.com/C0rT9.png
It may not be immediately obvious what the problem is, especially as we software engineers are notoriously bad at picking up on design details, but there is a clear lack of font consistency in the above screenshot. The familiar Roboto typeface is there in a couple of places, but alongside it is something decidedly non-Roboto (it isn't Droid Sans either - Roboto's pre-ICS predecessor). What the hell was going on? My app didn't use any custom fonts of its own and the there had never been any similar issues on other ICS devices. Roboto was purpose designed to be open source friendly, royalty free and part of AOSP so there was no reason for Amazon not to make full use of it.
I immediately assumed I had botched my styles somehow, but even in my out-of-the-box Holo preference activity, Roboto was nowhere to be seen outside the of Action Bar:http://i.imgur.com/zvjhF.png
I then downloaded the Official eBay app from the Amazon app store onto my Kindle to see if other apps exhibited the problem:http://i.imgur.com/4mQJ2.png
Aarrgh... my eyeballs!! Notice how particularly ugly this font is when the bold weight is applied, which introduces blurring artefacts that completely destroy the rhythm of the text. Roboto was created specifically for the requirements of UI and high-resolution screens. This font, whatever it is, clearly was not.
The next step was to create a simple app from scratch to try to establish the criteria for which either Roboto or this rouge font (which by this point I had coined "Fauxboto") was being used. Was it a scaled pixel threshold, a style property or something else entirely?http://i.imgur.com/7oUfg.png
Fortunately it became obvious pretty quickly where the problem lay. Notice in the above screenshot that the Roboto typeface is used only when a textAppearance style is specified, but crucially NOT when that value is ?android:attr/textAppearanceSmall
. After a quick glance through the AOSP styles.xml, it turns out that the default textAppearance value for an unstyled TextView (as well as a bunch of other derivative widgets) is indeed ?android:attr/textAppearanceSmall
So the rouge font appears because of Amazon's implementation of @android:style/TextAppearance.Small
(and its inverse cousin). Only the GPL components of Amazon's Kindle OS are open source, so I have no way to see what that implementation is. Since I can't imagine this behaviour to be a deliberate choice on their part, it must be a bug.
Fortunately the power of Android's styles and themes framework lets us fix this in our own apps. First we must declare our own styles for TextAppearance.Small
. We will inherit from android:TextAppearance
because we know that that particular style does not exhibit the bug on these devices:
<!-- fixes for broken Holo text appearances on Kindle Fire 2/HD -->
<style name="TextAppearance.KindleFix.Small" parent="android:TextAppearance" >
<style name="TextAppearance.KindleFix.Small.Inverse" >
Now in our application's base theme we must redefine the appropriate attributes to reference our custom styles:
<style name="Theme.Mine" parent="@android:style/Theme.Holo">
Depending upon how you have styled your application and the UI widgets you use, that small change will fix about 90% of the occurrences of the rouge font. What it does not do is fix the text appearance for any styles that inherit
from Amazon's broken implementation of TextAppearance.Small
(or the Holo derivative). Fortunately there appears to be only a handful these (like Action Bar subtitle, Action Bar item menu text and switch) and you can cherry pick them from the AOSP styles.xml for the widgets you are using and re-implement them accordingly.
After making these changes my app now looks like this, with Roboto font consistency and balance to the Holo theme restored. I can now focus on addressing my app's own design issues without being affected by those in the underlying platform:http://i.imgur.com/wIOMZ.png
I'm not aware of any formal mechanism to report bugs like this to Amazon, short of posting in their app distribution developer forums. If anyone knows someone who works on the Kindle Fire OS team, please direct them to this post. Amazon's own apps on Kindle Fire use a very customised theme (though curiously it is not a Theme.DeviceDefault
implementation) so I'm not surprised that they do not exhibit this issue. However, fixing this bug will automatically make many of the 3rd party apps on their devices look 100 times better.