安卓系统可以在多种设备上运行,包括电话,平板和电视等。作为开发者,设备的多样性给app提供了巨大的市场。为了让app在所有适配所有的设备,app应该可以兼容一些设备的特性,并提供一些弹性的用户界面来适应不同的屏幕尺寸。
为了更容易达成这个目标,安卓提供了动态的框架来让我们在静态文件里边(比如为不同的屏幕大小配置不同的xml布局)来配置app资源。安卓系统会根据当前的设备配置来使用合适的资源。所以进行一些提前的设计和额外的资源,我们就可以发布一个apk来适配不再的设备。
如有必要,我们还可以指定app的特殊要求,决定哪些设备可以从GooglePalyStore下载安装我们的app。本文会介绍如何来限定哪些设备可以安装我们的app。
兼容性的意义
安卓开发文档中经常会出现的兼容性这个词。主要有两种兼容性:设备兼容性和app兼容性。
因为安卓系统是开源的,所以任何硬件开发商都可以生产安卓设备。但是,只有这个设备可以运行安卓app的才是安卓兼容的。安卓运行环境是由安卓兼容项目定义的,每个设备只有通过兼容测试才是兼容的。
作为开发者,我们不需要关心设备的兼容性。因为只有兼容的设备才能使用googlePlayStore.所以我们可以确定,从googlePlayStore安装我们的app的都是兼容的设备。
但是,我们需要关心每个设备的配置。因为安卓设备的配置太多,一些特性不是所有的设备都有。比如,有些设备,没有指南针,如果我们的app需要使用到指南针,那么我们的app就只对那些有指南针的设备兼容。
适配APP
我们可以使用API来兼容一些特性。一些是硬件方面的(比如,指南针),一些是软件方面的(比如UI组件),一些是系统版本方面的。每个设备的支持都不尽相同,所以我们需要根据app的情况来适配APP.
为了app用户最多化,我们应该尽可能使用一个apk来适配最多的设备。通常,我们可以两种方法,1是在运行时禁用一些非核心功能,2是为不同的配置提供不同的app资源(比如,不同的屏幕尺寸提供不同的布局文件)。但是,以下情况,我们可以限制设备来通过googlePlayStore来安装我们的app:
1.设备特点。
2.系统版本。
3.屏幕尺寸。
设备特点
安卓为那些不是所有设备都兼容的硬件和软件提供了特性ID,这样我们能更方便的根据这些特性来控制app的适配。比如,指南针的特性ID是FEATURE_SENSOR_COMPASS,UI组件是FEATURE_APP_WIDGETS.
必要时,如果用户的设备不提供我们在清单文件中声明的
比如,如果我们的app需要指南针功能,可以在清单文件中做如下声明:
...
GooglePlayStore会对比app需要的特性和设备的特性来决定应用是否可以兼容每个设备。如果设备没有app的需要的特性,用户是无法安装应用的。
但是,如果应用的核心功能不需要这个特性,我们可以把这个特性的required属性设置为false,然后在运行时检查这个特性。如果当前设备没有这个特性,我们可以适当的减少app的功能支持。比如,我们可以使用hasSystemFeature来检查设备是否有某一特性:
PackageManager pm = getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) {
// This device does not have a compass, turn off the compass feature
disableCompassFeature();
}
想了解更多,请参阅GooglePlay.
注意,一些系统权限隐式的需要设备特性。比如,蓝牙权限隐式的需要设备的FEATURE_BLUETOOTH特性的。我们可以根据设备的特性来禁用过滤,通过设置
系统版本
不同设备运行的系统版本也不同,比如android 4.0或者4.4。每个后边的版本通常都新增了一些新的API.为了区别哪些API是可用的,每个系统版本对应了一个API级别.比如android 1.0是API1,android4.4是API19.
我们可以在
比如,日历是在android4.0(API14)才加入的。如果app必须使用到这些API,我们应该在这样声明:
...
minSdkVersion属性声明了app兼容的最低版本,targetSdkVersion属性声明了app优化的最高版本。
后续版本的总是兼容使用前边版本的API构建的app.所以我们的app在使用现有的api时应该总是兼容后续的系统版本。
注意:targetSdkVersion并不会阻止app安装在更高的系统版本上,它的重要性在于这表明了系统是否应该在新的版本中继承这些变更。如果我们没有更新targetSdkVersion到最新版本,当app在最新版本的系统上运行时,系统会认为app需要向前兼容。比如,Android 4.4中,使用AlarmManager创建的闹钟默认不是非常准确,这样系统可以批量管理闹钟达到省电的目的,但是如果设置的target API低于19,那么系统还是会保留并使用之前的API.
但是,如果app使用了最新的API,而它又不是app的核心功能,我们应该在运行时检查API的版本,当API版本低的时候,阉割掉一部分功能。这种情况下,设置minSdkVersion为最低的版本,然后比较当前系统版本。例如:
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();
}
屏幕配置
安卓设备从电话,到平板和电视,大小不一。为了能够根据屏幕对设备进行分类,安卓定义了两种:屏幕尺寸(屏幕的物理大小)和屏幕密度(屏幕上每像素的物理密度,就是DPI).为了简化配置,安卓简单的把它们进行了分组:
四组: small, normal, large, and xlarge.
和几组通用的密度:mdpi (medium), hdpi (hdpi), xhdpi (extra high), xxhdpi (extra-extra high), and others.
通常,我们的app应该适配所有的屏幕大小和密度,这样系统可以对我们的布局和图片资源等对每个设备进行调整。但是需要我们额外添加布局和图片资源。
商用APP的可用性控制
除了根据设备特性进行app的限制安装,可能有商业或者法律的因素,也需要对app的安装进行限制。比如,伦敦的地铁时刻表不应该让英国以外的人使用。对于这种情况,googlePlayStore提供了过滤功能,让我们根据用户的地区或者网络情况来限制使用。
技术兼容性的过滤(比如需要硬件的支持)通常是根据APK文件里包含的信息。但是对于非技术因素的过滤(比如地理区域)通常是在googlePlay的开发都控制台上的。