How Android Scales Apps for Different Screen Sizes

By Ryan Whitwam

Android is doing a lot more than you would expect when you open an app.

With all the interest around tablets running Google's Android operating system, it's natural to wonder how well existing phone applications will work. The screen on the Galaxy Tab, for instance, is 1024x600. All the devices developers had to previously support topped out at WVGA 800x480 resolution. The differing sizes also affects the pixel density, which can have an effect on apps. The Android OS has underlying features and APIs to let developers easily support different screen sizes so their apps can scale. 


What is supported

The system understands screen configuration in terms of DPI, and physical size. These are grouped into categories: low DPI , medium DPI, and high DPI for density; and small, normal, and large for the actual size. These are not meant to be hard and fast measurements of the device screen. They just give developers a place to look if they want to custom design the UI for different display types.  

When we say low DPI, we're talking about QVGA 340x320. That's the lowest you're likely to see on any sort of Android smart phone. Medium DPI is referring to HVGA 480x320, like the original G1. High DPI can mean WVGA 800x480 all the way up to higher resolutions like the Samsung Galaxy Tab's 1024x600. The small, normal, and large screen size identifiers are more sweeping. Small would be considered 3.2-inches and under, normal is up to about 4-inches, and large is anything bigger than that. Note that there is a fair amount of overlap in these approximations (see the graphic). For example, a WVGA screen could still be considered 'normal' despite having high pixel density.  

How developers can plan for different screens

Android will scale content, true, but that might not always be the most desirable. If application resources are made for a small, lower-resolution display, the result of a software-based scale could be a little ugly. Simply using high quality graphics can solve some of this, but if developers want real polish, they can specify size and density-specific resource content for use in rendering the app. They can call out size-specific resource qualifiers 'large', 'normal', and 'small'. Similarly, devs can use the qualifiers hdpi (high), mdpi (medium), and ldpi (low) for density-specific resources. Developers can include app elements for each one of these if they so choose. If not, Android still manages to scale (more about that below).

The other developer API for controlling multi-screen rendering is less about choosing rendering elements, and more about specifying allowed dimensions. This will control what screen an app can be displayed on. There are four options for developers to specify what screens the app can scale to. This is controlled with a  manifest element called <supports-screens>. This is followed by one of the four options: android:largeScreens, android:normalScreens, android:smallScreens, and android:anyDensity

Developers can specify that their app is only for one rendering size by setting one of these values to 'true', and leaving the others 'false'. In most versions of Android, the android:anyDensity value is left as 'true' by default. If someone chose to leave only android:normalScreens active, this would cause the app to be rendered with black space around it on some larger screens. The pixel density is the deciding factor here.

What happens behind the scenes

When an app is lunched, three main processes kick in to render the app to a particular screen. The OS will first pre-scale the app resources. Loading and scaling the application resources is perhaps the most important part of this process. App resources are things like image assets to be displayed in the app. The system will match the density of the current screen to any elements provided. This is where those density-specific resource qualifiers mentioned above come into play.  
If an app has the matching resources for a particular display, no scaling happens. The content is simply rendered as is. If no matching resources are available, Android will use whatever the developer has provided, and scale it to the correct approximate density. So if the platform knows that the device has a high density screen, it will load elements qualified with 'hdpi' and will not scale them. If those resources don't exist, it will scale up the default resources. Depending on the quality of the default resources, this can look just fine. The resulting content is mapped to the available screen real estate.

and HVGA screen. The OS will actually lie to an HVGA app, and report a smaller resolution of  320x533, then map the coordinates to the actual WVGA 800x480 screen. This step makes a great many older apps usable on newer WVGA phones. The same thing works in reverse, but an app that is designed specifically for a large screen, might not be usable if its elements are shrunken down. 

Finally, Android will render in compatibility mode apps that have sizes locked, but cannot scale to the current screen. This is the danger zone for tablets. If an app declares only android:normalScreens, but the device has a large, medium density screen (this would be a physically larger screen with fewer pixels), the app will render at its native 1:1 pixel resolution, with the black space around it as mentioned above. The Galaxy Tab is being reported as hdpi, so this should usually not be an issue  

So that's how Android maintains a modicum of resolution and density independence in its apps. Developers that take advantage of Android's features can have a solid, multi-screen app experience. Still, some developers choose to lock down their app rendering because they are trying to design a particular experience. Some may even hard code pixel values or use the AbsoluteLayout container (deprecated in Android 1.5). These practices throw a wrench in the whole elegant machine that is Android's screen scaling. But we feel that overall, many of your favorite apps should scale just fine. Some of them might not be the prettiest, but that's surprisingly easy to fix. 
Image credit: Google, Slashgear