Android is designed to run on many different devices, such as phones, tablets, and televisions. The range of devices provides a huge potential audience for your app. For your app to be successful on all devices, it must tolerate feature variability and provide a flexible user interface that adapts to different screen configurations.
To help with device compatibility, Android provides a dynamic app framework in which you can provide configuration-specific app resources in static files, such as different XML layouts for different screen sizes. Android then loads the appropriate resources based on the current device configuration. With forethought to your app design and additional app resources, you can publish a single application package (APK) that optimizes the user experience on a variety of devices.
If necessary, however, you can specify your app's feature requirements and control which types of devices can install your app from the Google Play Store. This document explains how you can control which devices have access to your apps and how to prepare your apps to reach the right audience.
What does "compatibility" mean?
With regard to Android development, there are two types of compatibility: device compatibility and app compatibility.
Because Android is an open-source project, any hardware manufacturer can build a device that runs the Android operating system. But a device is "Android compatible" only if it can correctly run apps written for the Android execution environment. The exact details of the Android execution environment are defined by the Android compatibility program. Each device must pass the Compatibility Test Suite (CTS) to be considered compatible.
As an app developer, you don't need to worry about whether a device is Android compatible, because only devices that are Android compatible include Google Play Store. So, if a user installs your app from Google Play Store, they are using an Android compatible device.
However, you need to consider whether your app is compatible with each potential device configuration. Because Android runs on a wide range of device configurations, some features aren't available on all devices. For example, some devices might not include a compass sensor. If your app's core functionality requires a compass sensor, then your app is compatible only with devices that include that feature.
Control your app's availability to devices
Android supports a variety of features your app can leverage through platform APIs. Some features are hardware based, such as a compass sensor; some are software based, such as app widgets; and some depend on the platform version. Not every device supports every feature, so you might need to control your app's availability to devices based on your app's required features.
To achieve the largest user base possible for your app, support as many device configurations as possible using a single APK or AAB. In most situations, you can do so by disabling optional features at runtime and providing app resources with alternatives for different configurations, such as different layouts for different screen sizes. If necessary, you can restrict your app's availability to certain devices through Google Play Store based on the following device characteristics:
Device features
To manage your app's availability based on device features, Android defines
feature IDs for any hardware or software feature that might not be
available on all devices. For example, the feature ID for the compass sensor is
FEATURE_SENSOR_COMPASS
,
and the feature ID for app widgets is
FEATURE_APP_WIDGETS
.
If necessary, you can prevent users from installing your app when their
devices don't provide a necessary feature by declaring the feature using a
<uses-feature>
element in your app's
manifest file.
For example, if your app doesn't make sense on a device that lacks a compass sensor, you can declare the compass sensor as a requirement with the following manifest tag:
<manifest ... > <uses-feature android:name="android.hardware.sensor.compass" android:required="true" /> ... </manifest>
Google Play Store compares the features that your app requires to the features available on each user's device to determine whether your app is compatible with each device. If the device doesn't have all the features your app requires, the user can't install your app.
However, if your app's primary functionality doesn't require a
device feature, set the
required
attribute to "false"
and check for the device feature at runtime.
If the app feature isn't available on the current device, gracefully degrade the
corresponding app feature. For example, you can query whether a feature is
available by calling
hasSystemFeature()
like this:
Kotlin
if (!packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) { // This device doesn't have a compass. Turn off the compass feature. disableCompassFeature() }
Java
PackageManager pm = getPackageManager(); if (!pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) { // This device doesn't have a compass. Turn off the compass feature. disableCompassFeature(); }
For information about all the filters you can use to control the availability of your app through Google Play Store, see the Filters on Google Play documentation.
Platform version
Different devices might run different versions of the Android platform, such as Android 12 or Android 13. Each successive platform version often adds APIs not available in the previous version. To indicate which set of APIs are available, each platform version specifies an API level. For example, Android 12 is API level 31, and Android 13 is API level 33.
You must specify the
minSdkVersion
and
targetSdkVersion
values in your build.gradle
file:
Kotlin
android { defaultConfig { applicationId = "com.example.myapp" // Defines the minimum API level required to run the app. minSdkVersion(30) // Specifies the API level used to test the app. targetSdkVersion(33) ... } }
Groovy
android { defaultConfig { applicationId 'com.example.myapp' // Defines the minimum API level required to run the app. minSdkVersion 30 // Specifies the API level used to test the app. targetSdkVersion 33 ... } }
For more information about the build.gradle
file, read
Configure your build.
Each successive version of Android provides compatibility for apps built using the APIs from previous platform versions, so your app is compatible with future versions of Android while using the documented Android APIs.
However, if your app uses APIs added in a more recent platform version, but
doesn't require them for its primary functionality, check the API level at
runtime and gracefully degrade the corresponding features when the API level is
too low. In this case, set the minSdkVersion
to the lowest value
possible for your app's primary functionality, then compare the current system's
version,
SDK_INT
,
to the codename constant in
Build.VERSION_CODES
that corresponds to the API level you want to check, as shown in the following
example:
Kotlin
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { // Running on something older than API level 11, so disable // the drag and drop features that use ClipboardManager APIs. disableDragAndDrop() }
Java
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { // Running on something older than API level 11, so disable // the drag and drop features that use ClipboardManager APIs. disableDragAndDrop(); }
Screen configuration
Android runs on devices of various sizes such as phones, tablets, and TVs. To categorize devices by their screen type, Android defines two characteristics for each device: screen size (the physical size of the screen) and screen density (the physical density of the pixels on the screen, known as DPI). To simplify the different configurations, Android generalizes these variants into groups that make them easier to target:
- Four generalized sizes: small, normal, large, and xlarge
- Several generalized densities: mdpi (medium), hdpi (high), xhdpi (extra high), xxhdpi (extra-extra high), and others
By default, your app is compatible with all screen sizes and densities, because the system makes adjustments to your UI layout and image resources as necessary for each screen. Provide optimized bitmap images for common screen densities.
Optimize the user experience by using flexible layouts as much as possible. Where there are layouts for large configuration changes, such as portrait and landscape, or large versus small window sizes, consider providing alternate layouts that are flexible to smaller changes in the configuration. This improves the user experience on form factors such as tablets, phones, and foldables. It also helps when windows change size in multi-window mode.
For information about how to create alternative resources for different screens and how to restrict your app to certain screen sizes when necessary, read the screen compatibility overview and see the large screen app quality guidelines.
Control your app's availability for business reasons
In addition to restricting your app's availability based on device characteristics, you might need to restrict your app's availability for business or legal reasons. For this type of situation, Google Play Store provides filtering options in the Play Console that let you control your app's availability for nontechnical reasons such as user locale or wireless carrier.
Filtering for technical compatibility—such as required hardware components—is always based on information contained within your APK or AAB file. But filtering for nontechnical reasons—such as geographic locale—is always handled in the Google Play Console.
Additional resources:
- App resources overview
- Information about how Android apps are structured to separate app resources from the app code, including how you can provide alternative resources for specific device configurations.
- Filters on Google Play
- Information about the different ways Google Play Store can prevent your app from being installed on different devices.
- Permissions on Android
- How Android restricts app access to certain APIs with a permission system that requires the user's consent for your app to use those APIs.