Supporting devices with different resolutions
My widget and WiFi manager were originally written using HTC Hero running Android 1.5, which has a default screen size – 320 by 480.
Making it available and working on devices that have other screen resolutions involved a few fairly simple steps. All the information can be found elsewhere, but I am going to summarize it here for convenience.
Enabling build-time support for devices with other resolutions
Support for a devices with non-default resolutions first appeared in Android 1.6. It is necessary to switch the project to at least this platform version. In Eclipse, use Properties -> Android -> Project Build Target.
Update your application’s manifest
Insert this into the manifest:
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="4" />
This marks your application as targeting Android 1.6, but being able to run on Android 1.5.
Care should be exercised to not directly call any new framework methods introduced in Android 1.6 – if so, the application will crash on Android 1.5. If necessary, use Java reflection to determine at runtime if newer framework classes and methods are available. If they are, again use Java reflection to invoke them.
Declaring support for display resolutions
Android 1.6 introduced a new manifest tag, for declaring which screen resolutions the application supports.
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" />
For each of the three screen sizes, you can declare whether the application is compatible. Without explicit support for smallScreens, the application will not be visible in Market on small screen devices (such as the HTC Tattoo).
This tag is important for one other reason: without it, Android effectively runs your application at the default resolution (320 by 480) and scales this image as a whole to fit the real screen. On high-res devices this looks really ugly, on low-res devices, just ugly.
Setting anyDensity to true means that your application runs at the real device resolution. If you used device independent pixels (dp or dip) in your layout files, you’ll be fine. If you used real pixels (px), then it’s time to update your layouts.
If you used AbsoluteLayout in your application, it’s time to convert – this layout is deprecated starting with Android 1.6.
This was the case in my widget, so I used RelativeLayout instead. To place individual views where needed, I used
android:layout_marginTop. This is the same as using
android:layout_y in AbsoluteLayout.
Providing alternate graphics
Once the above is done, your application should already look pretty good.
At this point, if you have any images (such as .png), they are still loaded by Android at default resolution (160 dpi) and scaled. This can cause them look blurry especially on higher resolution devices (480 by 800 and 480 by 854).
To improve on this, it’s possible to provide alternate images for low- and high-density resolutions.
If your build target is set to Android 1.6 or above, you can create folders inside res that are specifically marked for certain resolutions. This can be done with any standard folder – layout, res, etc and is described in detail in the Dev Guide.
For high-res images, use a folder named “drawable-hdpi-v4”. If alternate low-resolution images are required, place them in “drawable-ldpi-v4”.
Note: the “-v4” at the end is needed (don’t use just “drawable-ldpi”, etc.) to hide alternate resources from Android 1.5. If the “-v4” is omitted, standard resolution devices running 1.5 will use the resources in “drawable-ldpi” and scale them up, which is definitely not what we want.
Tips for creating alternate images
High-res images are scaled by a factor 1.5 relative to default ones. Low-res images are 3/4 the size.
I use Photoshop to create graphics for my apps. If you create your images using shapes (rectangles, ellipses, round-rects), they should scale quite nicely. Rasteizing artwork should be avoided – so don’t use “Rasterize Layer” command or pixel-oriented tools.
Photoshop has a convenient way of exporting your artwork into .png. File -> Save for Web & Devices, which does two things:
First, it’s possible to resize artwork during export, which is convenient for creating lower-resolution images.
Second, the exported images are optimized and have lower file sizes compared to just saving as .png (using File -> Save As).
I design my artwork at default resolution (320 by 480) using shapes. To get high resolution images, I first save the original file under a new name, then use Image -> Image Size to upscale the image. Finally, I save the image as .png using File -> Save for Web & Devices as described above.
Higher resolution images are pretty much necessary, but I also found that it’s a good idea to provide low-res versions (drawable-ldpi) as well. Photoshop does a better job at scaling graphics than Android can at resource load time. I save low-res images from the same Photoshop file as used for normal resolution, setting their size during “Save for Web & Devices”.
More devices, happier users
I hope these tips should be useful for creating applications that reach out wider and look better on a variety of devices. And this means more happy users!