Android 提供了不少 feature,有的基于硬件,例如指南针传感器。有的基于软件,例如 widget。还有的是基于 OS 版本。由于并非每一个设备都支持全部的 feature,因此咱们要基于设备所具有的 feature 对 App 的 feature 进行控制。html
一般为了用户量,咱们要尽可能让咱们的 App 能在更多的设备运行。为了达到这个目的,有的时候咱们要在运行时关掉一些非必须的功能 ,由于有的设备可能没有相应的 feature。而且提供不一样的可选配置,例如为不一样屏幕尺寸提供不一样的 layout 文件。从另外一方面讲,由于有的设备太老旧,或者说支持这样的设备开发成本太大。咱们就能够经过如下几方面来控制 App 能够安装在哪些设备上。android
无论是基于硬件或者是基于软件的 feature ,Android 都为每个 feature 都定义了一个 feature ID。例如,指南针传感器的 ID 是 FEATURE_SENSOR_COMPASS, widget 的 ID是
appFEATURE_APP_WIDGETS
。
这样若是咱们在 manifest file 里面声明了一个 feature,那么那些没有这个 feature 的设备就不能安装咱们的 App。ide
例如,若是咱们不肯定目标设备是否有指南针传感器,可是咱们的 App 又必需要这个传感器才能运行,咱们就能够在 manifest 里面声明咱们的 App 必需这个 feature:布局
<manifest ... > <uses-feature android:name="android.hardware.sensor.compass" android:required="true" /> ... </manifest>
Google Play Store 会拿 App 所需的 feature 列表和用户设备所具备的 feature 作对比,来识别某一个设备是否能安装这个 App。若是设备不支持这里声明的任何一个 feature,那么该设备就不能安装这个 App。gradle
另外一方面,若是一个 feature 是否存在并不影响 App 的主要功能,那么咱们能够把 required 设置为 false ,这样即便没有这个 feature 的设备也能够安装该 App,而后在运行时检测设备是否有这个 feature。若是设备没有这个 feature,这时候咱们再关掉 App 相应的功能。下面是在 runtime 检测一个 feature 是否存在的例子:优化
PackageManager pm = getPackageManager(); if (!pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) { // This device does not have a compass, turn off the compass feature disableCompassFeature(); }
更多关于 feature 过滤的功能请参考 Filters on Google Play。ui
注意:有的权限请求声明会默认包含 feature 请求声明。例如若是 App 声明了须要 BLUETOOTH 权限,那么实际上也等于声明了目标设备须要有
googleFEATURE_BLUETOOTH
feature 。基于此,咱们能够再显式地作一个 feature 声明,并把 required 设置为 false 来关闭这个 feature 过滤,这样没有蓝牙的设备也能够安装咱们的 App。详情参考 Permissions that Imply Feature Requirements。
不一样的设备运行的 Android platform 版本不一样,例如 Android 4.0、Android 4.4。固然新的 API 不会加到旧版本上去。为了便于区分 API 集,每一个 Android platform 版本都会有一个 API level。例如 Android 1.0 的 API level 是 1,而 Android 4.4 是 API level 19。spa
经过设置 <uses-sdk>
的 minSdkVersion
值,API level 能够用来声明 App 能够兼容的最低版本。例如,Android 4.0(API level 14)才有 Calendar Provider API 集。若是你的 App 没这个 API 不行,那么你就应该把 API level 14 做为 App 支持的最低版本。
minSdkVersion
用于声明 App 兼容到的最低版本。
targetSdkVersion
用于声明 App 已经充分使用的最高版本。
须要注意的是,<uses-sdk>
中的声明会被 build.gradle
file 覆盖。因此若是你使用 Android Studio,必须在 build.gradle
中声明 minSdkVersion
和
targetSdkVersion
,而不是在
manifest
中声明它们:
android {
defaultConfig {
applicationId 'com.example.myapp'
// Defines the minimum API level required to run the app.
minSdkVersion 15
// Specifies the API level used to test the app.
targetSdkVersion 26
...
}
}
关于 build.gradle
详情参考 how to configure your build。
若是 targetSdkVersion
的值为18,而你的手机是 Android 4.4(19),这个手机仍然能够安装你的 App。可是这个属性依然很重要,由于系统能够经过它来识别你的 App 是否使用新版新的特性。若是你不把 targetSdkVersion
写成最高版本,那么当 App 在高版本上运行的时候,系统会让你的 App 用一些旧版本的 API。例如,Android 4.4 中,默认状况下经过 AlarmManager
API 集建立的 alarm 的提醒时间不是很精准,这样系统就能够批量处理这些 alarm 以节约电量。若是你的 targetSdkVersion
小于19,那么系统仍然会用以前的版本的行为来建立 alarm。
另外一方面,若是咱们的 App 使用了一些高版本才有的 API 集,可是没有这些 API 也不影响主要功能,那么咱们就能够在运行时检测 API level ,若是版本过低就关闭相应的 App 功能。这种状况应当把 minSdkVersion
设置为 App 主要功能所需的最低版本,而后在运行时拿当前系统版本
SDK_INT
和 App 想要的 API 版本常量做比较:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { // Running on something older than API level 11, so disable // the drag/drop features that use ClipboardManager APIs disableDragAndDrop(); }
从手机到平板,包括电视,Android 程序能够在不少尺寸的设备上运行。为了对这些设备的屏幕进行归类,Android 为全部的设备定义了两个参数:屏幕尺寸和屏幕密度(屏幕上的像素密度,就是DPI)。为了便于使用,Android 对它们进行了归类:
屏幕尺寸分为四类:small, normal, large, 和 xlarge.
像素密度分为:mdpi (medium), hdpi (hdpi), xhdpi (extra high), xxhdpi (extra-extra high), and others。
默认状况下系统会根据实际屏幕参数对你的布局及资源图片进行适当的调整,因此你的 App 能够兼容全部屏幕尺寸和像素密度的屏幕。可是为了能在各类设备上有更好的用户体验,你应该为不一样屏幕尺寸提供对应的布局,而且基于常见像素密度的屏幕,对图片资源进行优化。
For information about how to create alternative resources for different screens and how to restrict your app to certain screen sizes when necessary, read Supporting Different Screens.