One of the great strengths of the Android platform is its support for a huge number and variety of devices. From your handset, tablet, and smartwatch to your television, car, and beyond, Android wants to be the all-purpose mobile computing platform. In terms of numbers, this approach has been very successful – there are likely more than 20,000 distinct devices at the time of this writing1. That’s far more than any competing platforms.
Supporting all these devices, though, poses a couple of challenges. Users expect apps to function consistently on every device, despite significant differences in hardware and software. Meanwhile, because of unique challenges in delivering Android software updates to users, developers cannot always depend on users having access to the latest Android releases. In fact, developers should anticipate most of their users to be running releases that are 18 months old or older2.
Without help from the Android team, developers would be forced to make some pretty ugly compromises in order to support most of their users. Fortunately, the Android team recognized that accommodating older devices and releases was strategically important. However, doing this in a way that doesn’t hamstring future releases presents an architectural challenge because the Android APIs obviously need to evolve over time. How can important new APIs be made available to the majority of Android users and not just those with newer devices lucky enough to run the latest releases?
The answer is one of the most important and peculiar design decisions made by the Android team: the Android Support Library.
What is the Android Support Library?
The Android Support Library was originally released in 2011 as the Android Compatibility Library. In over 75% of all app installs, it is the most widely used Android library3. Android developers already know that the Android Support Library provides newer APIs for older releases. But that’s not the whole story.
The Android Support Library is not actually a single library, but rather a collection of libraries that can roughly be divided into two groups: compatibility and component libraries.
Each library uses a naming convention that identifies the minSdkVersion your project must have in order to use it. This can be a little confusing, because it seems natural to think that support libraries with higher version numbers include the features from previous libraries (you might think v7-appcompat improves upon and includes all features from v4). In most cases, this is incorrect. To add to this confusion, libraries themselves have a revision number. For example, “AppCompat v21” actually refers to support library v7-appcompat, revision 21.
Compatibility libraries focus on back porting features from newer framework releases so that devices running previous releases can take advantage of the newer APIs. The major compatibility libraries are v4 and v7-appcompat.
Large and monolithic, the v4 library is the granddaddy of them all. It includes many features and, as its name suggests, supports back to API 4. In addition to support implementations for major classes like Fragment and Loader (which were both introduced in the framework in API 11), you’ll also find several widely-used classes not present in the framework at all, such as ViewPager and DrawerLayout.
Don’t let its name fool you: despite supporting all the way back to Android 1.6, this remains a very widely used and important library. And because of support library dependencies, it’s often hard to avoid the use of v4 entirely.
Often simply referred to as AppCompat, the v7-appcompat library provides support implementations for ActionBar (introduced in API 11) and Toolbar (introduced in API 21) for releases back to API 7. It requires the v4 library but does not include it. Thus, any feature dependent upon v7-appcompat is also dependent upon v4.
Under the Hood
The compatibility libraries largely use shims to back port features. These compatibility shims are thin wrappers around components that pass calls through to the underlying framework implementation if used on a release that supports the API. On older releases, the shims instead call the support implementation, perhaps with slightly different or reduced functionality.
However, in some cases a compatibility shim is not used. Instead, in these cases the support library always uses its own implementation in place of the framework implementation — even when the release supports the framework implementation. One major example of this is v4 support Fragments.
This is a very interesting decision, one that ripples across the entire Android framework. Android has created an entirely different support implementation of these major features, duplicating a lot of functionality, and packaging it as a different set of classes and resources. These support implementations live in parallel to their framework cousins, complete with their own inheritance hierarchy, revisions, and bugs.
Google claims that in these cases most of the APIs are the same, except that they belong to a different package and have minor differences in a few method names and signatures. However, in practice, there are some inconsistent and not so insignificant API differences between support and framework implementations – differences that will likely grow over time.
Furthermore, in some cases, developers may think they have the choice between framework and support implementations of a particular feature, only to find out that support dependencies dictate that decision for them. For example, the v7-appcompat library enables developers to use Material Design UI features introduced in API 21. However, doing so requires that all activities extend from AppCompatActivity, which extends from the v4 support FragmentActivity. So, developers targeting anything less than API 21 and wishing to use Material Design UI features are forced to use v4 support Fragments, rather than framework Fragments.
Google considers use of the support libraries a best practice, even if not necessarily required. It includes v7-appcompat and v4 libraries in most of its sample code as well as in Android Studio’s new project templates. Google is clearly investing significant effort in these compatibility libraries and expects developers to heavily rely upon them.
In addition to compatibility libraries, the Android Support Library also provides smaller, more modular component libraries that enable developers to add features that are otherwise not part of the standard framework. These self-contained libraries can be easily added or removed from a project without concern for dependencies. There are several valuable component libraries to consider:
- v7-recyclerview: provides the RecyclerView component, which efficiently displays and animates large amounts of data and is designed to replace ListView
- v7-cardview: provides the CardView component, enabling the cards UI design pattern
- v7-gridlayout: provides the GridLayout class, which enables organizing UI elements into a rectangular grid
- v7-mediarouter: provides MediaRouter and related classes, enabling Google Cast support
- v7-palette: provides the Palette class, which enables developers to identify primary colors in an image
Adding any of these components to your gradle-based project is as simple as adding a dependency to your build script.
Beyond the benefits of convenience and modularity, separating these components into their own libraries allows Google to release important APIs outside of the framework. This allows feedback to be gathered and design iterated before possibly being finalized into the framework, where breaking changes would be much more difficult make.
The Android Support Library also contains a few other libraries that are used less often, but still worth mentioning:
- v8: provides support for RenderScript (introduced in API 11) back to API 8
- v13: provides additional compatibility support for the Fragment UI pattern and bundles the v4 library
- v17: provides support for building TV UIs
- multidex: provides support for building apps with multiple DEX files
- annotations: provides support for annotations like @NonNull and @IntDef
When should I use the Android Support Library?
You should use one of the support libraries when you need specific framework features that are newer than the minSdkVersion of your app or that are not available in the standard framework.
However, Google considers the general use of the support libraries to be a best practice, even if not necessarily required.
Which version of the Android Support Library should I use?
In short, use the version your application can support that has the features you need. Some features are modular. For example, to use RecyclerView, simply add the v7-recyclerview dependency identifier to your gradle build script.
If you need one of the compatibility components from v4, you can use v13 instead if your minSdkVersion supports that, since it bundles v4. Otherwise, if you need to support API versions <13 and need a v4 component, use the v4 support library itself.
However, be aware that dependencies in support libraries may dictate which particular support library is used.
In order for Android to remain successful by Google’s standards, it must continue to have as wide a reach as possible. A major component of that goal is the ongoing support for an exploding number of devices, many of which may never have access to the latest Android releases.
While not always elegant or entirely painless, the Android Support Library achieves this by enabling developers to use important new APIs on older releases while also providing useful components that exist outside the standard Android framework. It’s an important part of Android development, and Android developers have a responsibility to understand and utilize it.