The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Dealing with Different Hardware

While a lot of focus is placed on screen sizes, there are many other possible hardware differences among different Android devices. For example, some have telephony features, while others do not.

There is a three-phase plan for dealing with these variations:

  1. Filter out devices that cannot possibly run your app successfully, so your app will not appear to them in the Play Store and they will be unable to install your app if obtained by other means
  2. React to varying hardware that you can support, but perhaps might support differently (e.g., choosing a particular flash mode for a device having a camera with a flash)
  3. Cope with device bugs or regressions that impact your application

This chapter will go through each of these topics.

Prerequisites

Understanding this chapter requires that you have read the core chapters of this book.

Filtering Out Devices

Elsewhere in the book, we discussed a few manifest entries that will serve to filter out devices that cannot run your app:

This section outlines other “advertisements” that you can put in the manifest to restrict which devices run your app.

uses-feature

The <uses-feature> element restricts your app to devices that have certain hardware features. For each element, you supply the name of a feature (e.g., android.hardware.telephony) and whether or not it is required:

<uses-feature
  android:name="android.hardware.camera"
  android:required="false" />

By default, android:required is set to true, so typically you will only see it in a manifest when it is set to false.

You might wonder why we would bother ever setting android:required to false. After all, that should have the same effect as not listing it at all. In practice, though, it has two major uses.

First, markets like the Play Store might highlight the fact that you can use a particular hardware capability, even though you do not strictly require it.

More importantly, you can use android:required="false" to undo a requirement that Android infers from your permissions. Requesting some permissions causes Android to assume — for backwards-compatibility reasons — that your app needs the affiliated hardware. For example, requesting the CAMERA permission causes Android to assume that you need a camera (android.hardware.camera) and that the camera support auto-focus (android.hardware.camera.autofocus). If, however, you are requesting the permission because you would like to use the hardware if available, but can live without it, you need to expressly add a <uses-feature> element declaring that the hardware feature is not required.

For example, in February 2010, the Motorola XOOM tablet was released. This was the first Android device that had the Play Store on it and truly had no telephony capability. As such, the XOOM would be filtered out of the then-Android Market (now Play Store) for any app that required permissions like SEND_SMS. Many developers requested this permission, even though their apps could survive without SMS-sending capability. However, their apps were still filtered out if they did not have the <uses-feature> element declaring that telephony was not required.

You can find a table listing Android permissions and assumed hardware feature requirements in the Android developer documentation.

uses-configuration

The <uses-configuration> element is very reminiscent of <uses-feature>: it dictates hardware requirements. The difference is two-fold:

  1. It focuses on hardware elements that represent different device configurations, meaning that you might use different resources for them
  2. It allows you to specify combinations of capabilities that you need

There are three capabilities that you can require via <uses-configuration>:

  1. The existence of a five-way navigation control, whether a specific type (D-pad, trackball, etc.) or any such control
  2. The existence of a physical keyboard, whether a specific type (QWERTY, 12-key numeric keypad, etc.) or any such keyboard
  3. A touchscreen

You can have as many <uses-configuration> elements as you need – any device that matches at least one such configuration will be eligible to install your app.

For example, the following <uses-configuration> element restricts your app to devices that have some sort of navigation control but do not necessarily have a touchscreen, such as a Android TV device:

<uses-configuration
  android:reqFiveWayNav="true"
  android:reqTouchScreen="notouch" />

uses-library

The <uses-library> element tells Android that your application wishes to use a particular firmware-supplied library. The most common case for this was Maps V1, which is shipped in the form of an SDK add-on and firmware library. This, however, has been deprecated for quite some time.

However, there are other firmware libraries that you might need. These will typically be manufacturer-specific libraries, allowing your application to take advantage of particular beyond-the-Android-SDK capabilities of a particular device. This is very uncommon nowadays.

The Google Play Store will filter out your application from devices that lack a firmware library that you require via <uses-library>. If the user tries installing your app by some other means (e.g., download from a Web site), your app will fail to install on devices that lack the firmware library.

If you conditionally want the firmware library — you will use it if available but can cope if it is not — you can add android:required="false" to your <uses-library> element. That will allow your app to install and run on devices missing the library in question. Detecting whether or not the library exists in your process at runtime is a matter if using Class.forName() to see if you have access to some class from that library, where a ClassNotFoundException means that you do not have the library.

Runtime Capability Detection

The preview of this section was accidentally identified as an Android 'tasty treat' by the Cookie Monster.

Dealing with Device Bugs

The preview of this section was eaten by a grue.