Targeting Different Device Configurations Android

Android devices come in all colors, shapes, and sizes. Sometimes you want to try to support all devices with a single application, and other times you want to limit the types of device configurations that your application can support. Really, it all comes down to knowing your user audience, so that they have positive experience (without excluding anyone unnecessarily).

Developers can target different device configurations using a number of Android Manifest tags, including <supports-screen>, <uses-configuration>, <uses-feature>, and <uses-sdk>.Developers can also use certain programming techniques to help ensure that applications are both forward and backward compatible.

Supporting Hardware Configurations

Let’s take a closer look at some of the Android manifest file tags that you can use in your application to help identify target device configurations and how they work:

  • You can use the <supports-screen> tag to limit what types of screens your application supports, as discussed earlier in the chapter.
  • You can use the <uses-configuration> tag to indicate the device configurations (generally related to input methods) used by the application, as well as whether or not they are required for the application to run properly.
  • You can use the <uses-feature> tag to indicate more features used by the application, as well as whether or not they are required for the application to run properly. Use this tag to specify what version of OpenGL ES your application supports as well as the optional hardware used (cameras, microphones, sensors). For a complete list of features available for use with this tag, see the feature constants defined in the PackageManager class documentation.
  • You can use the <uses-sdk> tag to limit what platforms can install your application to a specific range of SDK versions (as defined by API levels).This information is enforced by the Android operating system.

Targeting Different Android SDK Versions

When a new version of the Android version is released, developers must take note of the new SDK components added as well as those that were deprecated. First and foremost, you want to make sure you use the <uses-sdk> tag correctly in your application’s Android manifest file.

You can also use some other techniques to help ensure compatibility with different Android SDKs, including

  • Determine whether or not to use a specific feature of the Android SDK based upon its API Level (the Android SDK version in which it was introduced)
  • Use Java reflection to conditionally load newer SDK features, while supportingdevices that run older versions of the platform

Determining When SDK Features Were Introduced

When developing an application that targets multiple platform versions, developers need to pay special attention to the API Level associated with a given package, class, method, or constant in the SDK. The API Level in which a given class, interface, or method was introduced is usually listed in the Android SDK documentation, as shown in Figure.

The API Level for a given SDK component might be shown in different places in the documentation:

For packages, classes, and interfaces, the API level is displayed in the top-right corner of the Java documentation (at the top).

How to determine the API Level for a specific package, class, or method.

How to determine the API Level for a specific package, class, or method.

  • For methods and constants, the API level is shown to the right of the method name in its description (toward the bottom of the class documentation).

Using Java Reflection to Ensure Backward Compatibility

Luckily, Android applications are written in Java, and the Java programming language supports reflection. What this means is that developers can programmatically retrieve methods and classes by name at runtime, if necessary.

This is especially helpful when you want your application to take advantage of new parts of the Android SDK while still supporting older versions. When using this technique, you must build your project against the older SDK version while running on the new SDK version. The reason this technique works is because you never reference new methods or classes that don’t exist directly in code. Instead, they’re conditionally loaded by passing in strings to the Java reflection methods.

Let’s look at a quick example. To get a method by name, use the getMethod() method (say that ten times, fast) of the static class object of the specific class you are interested in. The following code retrieves a reference to the getExternalStoragePublicDirectory() method of the Environment class using Java reflection. This particular method was introduced in API Level 8 (Android 2.2) and therefore not available in previous versions of the platform:

Method methodExternalStoragePublicDirectory;
try{
methodExternalStoragePublicDirectory =
Environment.class.getMethod(
“getExternalStoragePublicDirectory",
new Class[] {String.class});
} catch (Exception e) {
// failed, not running API Level 8
// plan to provide alternate functionality
}

If the method is available, calls can then be made using the method External Storage Public Directory object, via its invoke() method. You could invoke the method as follows:

methodExternalStoragePublicDirectory.invoke(null, picture_directory);

Using these techniques enables the developer to maintain backward compatibility in her applications while taking advantage of the great new features crammed into newer versions of the Android SDK. Used judiciously, this technique can save time and effort and avoid the need to provide different versions of the application for different platform versions (often confusing to users).

It’s best not to over-use this technique—at some point, the application might be using so many of these features that the effort to implement and use Java reflection to support special cases becomes too great. Java reflection also introduces a performance penalty. Making a method call through the invoke() method is slower than a regular method call and common patterns involve placing all the reflection logic in a new class to abstract and simplify the use of it. This adds yet another layer to the call stack, though. This technique also makes your code harder to read and maintain.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Android Topics