英文原文:http://developer.android.com/guide/topics/manifest/uses-feature-element.html
采集(更新)日期:2014-7-7
搬迁自原博客:http://blog.sina.com.cn/s/blog_48d491300100zmwf.html
<uses-feature android:name="string" android:required=["true" | "false"] android:glEsVersion="integer" />
<manifest>
声明一项 <uses-feature>
的目的,是为了把应用程序所依赖的软硬件特性告知应用程序之外的对象。 本元素给出了一个 required
属性, 用于指定应用程序是否必需该项特性,也即不声明该项特性的话就无法正常运行; 或者最好是提供该项特性,但没有的话也能运行。 由于每种 Android 设备提供的特性各不相同, <uses-feature>
元素发挥着重要作用, 应用程序可以用它来描述其用到的各种设备特性。
应用程序声明的多项设备特性应该对应于 Android PackageManager
中的相关常量,为了方便起见,在本文最后的 Features 参考手册中已将这些常量列出。
由于每一项设备特性必须放在独立的一条 <uses-feature>
元素中声明, 如果应用程序需要用到多项特性,就需要声明多个 <uses-feature>
元素。 例如,假设应用程序需要使用蓝牙和摄像头设备,则应声明两个元素:
<uses-feature android:name="android.hardware.bluetooth" />
<uses-feature android:name="android.hardware.camera" />
通常,应该确保为应用程序需要的所有特性均声明了 <uses-feature>
元素。
<uses-feature>
元素的声明仅仅是告知性质的,这意味着 Android 系统本身不会在安装程序前检查设备是否支持这些特性。 不过,其他服务(如 Google Play )或者其他应用程序可以检查 <uses-feature>
声明来进行相应处理或与本应用程序进行交互。 因此,对需要用到的所有特性都进行声明(如下表所示)是非常重要的。
有些设备特性可能会存在一些特殊的属性,用于定义该特性的版本,比如 Open GL 版本(用 glEsVersion
声明)。 其他的一些与硬件是否就绪有关的特性,比如摄像头,则通过 name
属性进行声明。
尽管 <uses-feature>
元素仅对 API 级别 4 以上版本的设备才有效,仍然建议所有应用程序都要包含本元素, 即使 minSdkVersion
小于等于“3”也应如此。 只是运行较低版本系统的设备会忽略本元素罢了。
注意 一旦声明了一项特性,请记得必须同时申请相应的权限。 例如,在使用摄像头 API 之前,还必须申请 CAMERA
权限。 权限申请使得应用程序有权访问相应的软、硬件,而声明需要用到的特性可以保证合适的设备兼容性。
android:name
android:required
android:name
属性给出的特性。
android:required="true"
”, 则表示当设备不提供指定特性时,应用程序就不能正常运行或未设计为能够正常运行。android:required="false"
”, 则意味着如果设备支持则应用程序将优先使用此特性,但设计程序时是考虑没有该项特性也能正常工作的。如未明确给出声明,则android:required
的默认值是“true
”
android:glEsVersion
应用程序应该在 Manifest 中至少定义一项android:glEsVersion
属性。 如果定义了两项以上的 android:glEsVersion
,将会采用数字最大的那个值,其他值将被忽略。
如果应用程序未指定 android:glEsVersion
属性, 则假定该应用程序仅需要使用 OpenGL ES 1.0,所有 Android 平台的设备都支持该版本。
应用程序可以认为:如果系统支持给定的 OpenGL ES 版本,则同时也支持版本更低的 OpenGL ES。 因此,如果应用程序同时需要使用 OpenGL ES 1.0 和 OpenGL ES 2.0,则必须指定为 OpenGL ES 2.0。
可在多种版本 OpenGL ES 上运行的应用程序只要指定所需的最低版本号即可。 (可以在运行时检测是否有高版本的 OpenGL ES 可用。)
有关使用 OpenGL ES 的详细信息,包括如何在运行时检测 OpenGL ES 的当前版本,请参阅 OpenGL ES 指南。
PackageManager
FeatureInfo
ConfigurationInfo
<uses-permission>
Google Play 会对应用程序的用户可见性进行过滤,因此用户只能看到和下载那些与自己的设备兼容的应用程序。 其中一种过滤方式是根据设备特性的兼容性。
为了确定应用程序与给定用户设备的兼容性, Google Play 将对比:
<uses-feature>
元素中声明的特性 为了保证设备特性的精确匹配,Android 包管理器给出了一组公开的特性常量,应用程序和设备共同使用这组常量来声明特性需求和支持。 合法的特性常量已在本文底部的设备特性参考表中列出,同时也在 PackageManager
类的文档中给出。
当用户打开 Google Play 时,应用程序会调用 getSystemAvailableFeatures()
查询包管理器以列出设备可用的特性。 在与用户建立连接时, Store 程序会把设备特性清单上传给 Google Play 。
每次把应用程序上传到 Google Play Developer Console 时, Google Play 会扫描该应用程序的 Manifest 文件。 它会查找 <uses-feature>
元素并综合其他元素进行评估, 比如某些时候会参考 <uses-sdk>
和 <uses-permission>
元素。 在收集完应用程序的设备特性需求后,它会将此清单作为与应用程序的 .apk
及版本相关联的基础元数据进行内部保存。
当用户在 Google Play 上搜索或浏览应用程序时,后台服务会把程序需求与用户设备可用的特性进行比较。 如果设备能够满足某个应用程序所有的特性需求, Google Play 就允许用户看见该应用,自然也会提供下载。 只要任何一个特性需求不能被设备支持, Google Play 就会滤除该应用,于是用户就看不到此应用程序,也就无法下载。
因为在 <uses-feature>
元素中声明的设备特性会直接影响 Google Play 对应用程序的过滤行为, 所以请理解 Google Play 如何评估应用程序的 Manifest 文件并建立特性需求清单,这点非常重要。 下一章节里给出了更为详细的说明。
显式声明的特性是指应用程序在 <uses-feature>
元素中声明的那些设备特性。 特性的声明可以包含一个 android:required=["true" | "false"]
属性(假定以 API 级别 5 以上版本编译), 该属性可以声明应用程序是否一定需要本特性,也即不为(“true
”)的话就无法正常运行; 或者当可用时应用程序是否优先使用它,但设计时是考虑没有该特性也能运行的(为“false
”)。
Google Play 按照以下方式对待显式声明过的特性:
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
android:required
属性, 则 Google Play 将假定此项特性是必需的,并据此进行过滤。一般情况下,如果应用程序是为 Android 1.6 以下版本进行设计的,那么系统 API 是不支持 android:required
属性的, Google Play 会假定所有的 <uses-feature>
声明都是必须满足的。
注意: 通过显式声明某项特性并包含 android:required="false"
属性,可以有效地禁用 Google Play 对该特性的所有过滤行为。
隐含特性是指程序正常运行所必需的,但 未 在 Manifest 文件的 <uses-feature>
元素中声明的那些特性需求。 严格意义上说,所有应用程序都应该确保对其需要的或用到的全部设备特性进行声明,因此对用到的特性缺少声明应该被视为差错。 然而,作为对用户和开发人员的保护措施, Google Play 会查找每个应用程序的隐含特性需求并为其进行过滤,就如同这些特性已经显式声明过一样。
应用程序也许需要用到某个特性,但却没有进行声明,原因可能是:
<uses-feature>
元素。 <uses-feature>
元素的名称拼写错了, 或把无法识别的字符串赋值给了 android:name
属性, 这些都会导致声明不合法。考虑到上述情况, Google Play 会尝试检查 Manifest 文件中的其他元素, 以便发现应用程序隐含的特性需求,特别是 <uses-permission>
元素。
如果应用程序申请了硬件相关的访问权限,即便缺少相应的 <uses-feature>
声明, Google Play 也会 假定应用程序需要使用这些底层硬件,也就是有这些特性需求 。 根据这些权限,Google Play 会把相应的底层硬件特性加入到应用程序的基础元数据中,并为其建立过滤器。
例如,假设应用程序请求了 CAMERA
权限, 但却没有声明对应 android.hardware.camera
的 <uses-feature>
元素, Google Play 将认为该应用程序需要使用摄像头,那么设备不提供摄像头的用户也就不会看到该应用程序。
如果不希望 Google Play 根据隐含的特性需求进行过滤,也可以禁用此功能。 只要声明一条 <uses-feature>
元素中显式声明该特性,且包含 android:required="false"
属性即可。 例如:为了禁用由 CAMERA
权限引发的过滤,可以将该特性声明如下:
<uses-feature android:name="android.hardware.camera" android:required="false" />
请了解 <uses-permission>
元素中的权限请求可能直接影响 Google Play 对应用程序的过滤行为,这一点非常重要。 后续章节隐含了特性需求的权限中列出了全部隐含了特性需求并将触发过滤行为的权限列表。
在为蓝牙特性确定过滤条件时, Google Play 适用的规则与上述情况略有不同。
如果应用程序在 <uses-permission>
元素中声明了 Bluetooth 权限, 但未在 <uses-feature>
元素中显式声明 Bluetooth 特性, Google Play 将会检查应用程序设计时在 <uses-sdk>
元素中指定的目标 Android 平台版本。
如下表所列,仅当程序声明最低目标版本为 Android 2.0 (API 级别 5)以上时, Google Play 才会启用对蓝牙特性的过滤。 不过请注意,如果程序在 <uses-feature>
元素中显式声明了 Bluetooth 特性,则 Google Play 仍将适用正常的过滤规则。
如果 minSdkVersion 是 |
或者 targetSdkVersion 是 |
结果 |
---|---|---|
<=4 (或未声明 uses-sdk ) | <=4 | Google Play 不会根据 android.hardware.bluetooth 的声明进行任何过滤 |
<=4 | > =5 | Google Play 将对不提供 android.hardware.bluetooth 特性的设备进行过滤(包括低版本的系统) |
> =5 | > =5 |
下面举例说明根据 Google Play 对蓝牙特性进行过滤的各种效果。
<uses-feature>
元素中声明 Bluetooth 特性。
<manifest ...> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-sdk android:minSdkVersion="3" /> ... </manifest>
<manifest ...> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" /> ... </manifest>
<manifest ...> <uses-feature android:name="android.hardware.bluetooth" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" /> ... </manifest>
android:required="false"
属性。 Android Market对所有设备关闭基于Bluetooth feature支持的过滤,
<manifest ...> <uses-feature android:name="android.hardware.bluetooth" android:required="false" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" /> ... </manifest>
可以利用 Android SDK 内的 aapt 工具来确定 Google Play 是否会根据声明的特性和权限对应用程序进行过滤。 只要运行带有 dump badging
参数的 aapt
即可。 aapt
将会解析 Manifest 文件,并按照 Google Play 的规则来确定应用程序需要的设备特性。
请按以下步骤使用此工具:
.apk
。 如果使用带 ADT 的 Eclipse 进行开发,请右键点击 project 并选择 Android Tools > Export Unsigned Application Package。 选中目标文件名和路径并点击 OK 。aapt
工具的路径,则请定位到其所在目录。 如果正在使用的 SDK 工具为 r8 以上版本,则可以在 <SDK> /platform-tools/
目录中找到 aapt
。 注意: 必须使用最新版的 Platform-Tool 组件所提供的 aapt 。 如果没有最新版本的 Platform-Tool 组件,请用 Android SDK Manager 下载。
aapt
:$ aapt dump badging < path_to_exported_.apk >
以下是前面第二个蓝牙例子的命令行输出示例:
$ ./aapt dump badging BTExample.apk
package: name='com.example.android.btexample' versionCode='' versionName=''
uses-permission:'android.permission.BLUETOOTH_ADMIN'
uses-feature:'android.hardware.bluetooth'
sdkVersion:'3'
targetSdkVersion:'5'
application: label='BT Example' icon='res/drawable/app_bt_ex.png'
launchable activity name='com.example.android.btexample.MyActivity'label='' icon=''
uses-feature:'android.hardware.touchscreen'
main
supports-screens: 'small' 'normal' 'large'
locales: '--_--'
densities: '160'
下列表格列出了与软、硬件特性相关的参考信息,以及可在 Google Play 中隐含声明特性的权限。
下表说明了最新版本的系统所支持的硬件特性描述符。 如果应用程序需要声明对某个硬件特性的使用需求,只要在一项 <uses-feature>
元素的 android:name
属性值中声明某个对应的描述符即可。
种类 | 描述符 | 说明 | 备注 |
---|---|---|---|
音频设备 | android.hardware.audio.low_latency |
应用程序用到低延迟音频通道,并对声音的输入输出延迟较为敏感。 | |
蓝牙 | android.hardware.bluetooth |
应用程序用到蓝牙通讯特性。 | |
android.hardware.bluetooth_le |
应用程序用到低功耗蓝牙通讯特性 | ||
摄像头 | android.hardware.camera |
应用程序用到摄像头。如果设备支持多个摄像头,则使用屏幕背面的后置摄像头。 | |
android.hardware.camera.autofocus |
子特性。应用程序用到摄像头的自动对焦功能。 | 这些子特性隐含声明了父特性 android.hardware.camera , 除非同时附带声明了android:required="false" 。 |
|
android.hardware.camera.flash |
子特性。应用程序用到摄像头的闪光灯功能。 | ||
android.hardware.camera.front |
子特性。应用程序用到正面的前置摄像头。 | ||
android.hardware.camera.any |
应用程序至少用到一个摄像头,无所谓其朝向,如果有连接的外置摄像头也可以。 如果不是非要使用后置摄像头的话,可优先选用本设置,而不是 android.hardware.camera 。 |
||
android.hardware.camera.external |
如果存在的话,应用程序使用外置摄像头。 | ||
红外 | android.hardware.consumerir |
应用程序用到红外(Consumer IR) 功能。 | |
定位 | android.hardware.location |
应用程序用到一个以上的定位特性,例如 GPS 定位、网络定位或基站定位。 | |
android.hardware.location.network |
子特性。应用程序用到粗略的定位坐标,此坐标来自基于网络的定位系统。 | 这些子特性隐含声明了父特性 android.hardware.location , 除非同时附带声明了android:required="false" 。 |
|
android.hardware.location.gps |
子特性。应用程序用到精确的定位坐标,此坐标来自全球定位系统 GPS 接收器。 | ||
话筒 | android.hardware.microphone |
应用程序用到话筒。 | |
NFC | android.hardware.nfc |
应用程序用到近场无线通信(NFC)特性。 | |
android.hardware.nfc.hce |
应用程序用到 NFC 卡仿真特性 | ||
传感器 | android.hardware.sensor.accelerometer |
应用程序用到加速度传感器给出的运动数据。 | |
android.hardware.sensor.barometer |
应用程序用到气压传感器。 | ||
android.hardware.sensor.compass |
应用程序用到来自地磁传感器(罗盘)给出的方向数据。 | ||
android.hardware.sensor.gyroscope |
应用程序用到陀螺仪传感器。 | ||
android.hardware.sensor.light |
应用程序用到光线传感器。 | ||
android.hardware.sensor.proximity |
应用程序用到接近度传感器。 | ||
android.hardware.sensor.stepcounter |
应用程序用到走步计数器。 | ||
android.hardware.sensor.stepdetector |
应用程序用到了走步探测器。 | ||
屏幕 | android.hardware.screen.landscape |
应用程序需要设备横向放置。 | 例如,如果程序需要纵向屏幕,应该声明 默认情况下,两种方向都不是必需的,这样在支持一个或两个方向的设备上都可以安装应用程序。 不过,只要有 Activity 需要运行于指定的方向上,并使用了 为了保持向下兼容,任何运行 API 级别 12 以下版本系统的设备,都被视为同时支持横向和纵向放置。 |
android.hardware.screen.portrait |
应用程序需要设备纵向放置。 | ||
电话 | android.hardware.telephony |
应用程序用到电话特性,比如电话的数据通讯服务。 | |
android.hardware.telephony.cdma |
子特性。应用程序用到 CDMA 电话特性。 | 这些子特性隐含声明了父特性 android.hardware.telephony , 除非附带了 android:required="false" 声明。 |
|
android.hardware.telephony.gsm |
子特性。应用程序用到 GSM 电话特性。 | ||
电视 | android.hardware.type.television |
应用程序设计为电视机用户的体验方式。 | 本特性的“television”定义为典型的客厅电视用户体验方式: 大屏幕显示,用户可坐得更远,主要的输入方式是方向键之类,一般不使用触摸屏或鼠标(指点设备)。 |
触摸屏 | android.hardware.faketouch |
应用程序用到了基本的触摸交互事件,比如“按下”、“抬起”和拖动。 | 一经声明,即表示应用程序兼容那些仅提供了仿真触摸屏(伪触摸屏)或更高级触摸屏的设备。 提供伪触摸屏的设备可向用户提供一种模仿了部分触摸屏功能的录入系统。 比如,可控制屏幕光标的鼠标或遥控器就提供了伪触摸屏功能。 如果应用程序需要基本的指点和点击交互(换句话说,仅用方向键是无法正常工作的),就应该声明本特性。 因为这是最低级别的触摸交互方式,应用程序也将能兼容那些可提供更复杂触摸交互方式的设备。 注意: 由于应用程序默认是需要 |
android.hardware.faketouch.multitouch.distinct |
应用程序在伪触摸屏上对两个以上的手指进行独立的跟踪。 这是 faketouch 的子特性。 | 一经声明,即表示应用程序兼容那些仅能独立跟踪两个以上手指操作事件的仿真触摸屏或更高级的设备。 与 |
|
android.hardware.faketouch.multitouch.jazzhand |
应用程序在伪触摸屏上对五个以上的手指进行独立的跟踪。 这是 faketouch 的子特性。 | 一经声明,即表示应用程序兼容那些仅能独立跟踪五个以上手指操作事件的仿真触摸设备。 与 |
|
android.hardware.touchscreen |
应用程序用到比基本触摸事件更加复杂的手势触摸功能,比如滑动。 这是基本 faketouch 特性的超集。 | 默认情况下,应用程序是必须使用本特性的。 这样,应用程序默认就不适用于那些仅能仿真触摸接口(fake touch)的设备。 如果应用程序需要能够适用于提供仿真触摸接口的设备(甚至是仅提供方向键的设备),则必须用带有 如果应用程序确实需要触摸屏接口(为了处理滑动之类的触摸手势),就不必进行任何声明,因为默认这就是必需的。 不过,最好还是对所有要用到的特性都进行显式声明,因此必要的话还是应该声明本特性。 如果需要用到更复杂的触摸操作,比如多个手指的手势,则应该声明后续的更为高级的触摸屏特性。 |
|
android.hardware.touchscreen.multitouch |
应用程序用到基本的两点触摸功能(比如夹的手势),但不需要多点独立跟踪。 这是 touchscreen 特性的超集。 | 本特性隐含声明了父特性 android.hardware.touchscreen ,除非同时附带了 android:required="false" 声明。 |
|
android.hardware.touchscreen.multitouch.distinct |
子特性。应用程序用到了高级的多点触摸功能,比如完全独立地跟踪两个以上的触点轨迹。 这是 multitouch 特性的超集。 | 本特性隐含声明了父特性android.hardware.touchscreen.multitouch , 除非同时附带了 android:required="false" 声明。 |
|
android.hardware.touchscreen.multitouch.jazzhand |
应用程序用到了高级的多点触摸功能,需要完全跟踪不超过五个触点的轨迹。 这是 distinct 多点触摸特性的超集。 | ||
USB | android.hardware.usb.host |
应用程序用到 USB 主机模式特性(作为接受 USB 设备连接的主机)。 | |
android.hardware.usb.accessory |
应用程序用到 USB 访问特性(作为 USB 设备并去连接 USB 主机)。 | ||
Wi-Fi | android.hardware.wifi |
应用程序用到 802.11 网络(Wi-Fi)特性。 | |
android.hardware.wifi.direct |
应用程序用到 Wi-Fi Direct 网络特性。 |
下表对最新版本系统支持的软件特性描述符给出了说明。 如果应用程序需要声明对某个软件特性的使用需求,只要在一项 <uses-feature>
元素的 android:name
属性值中声明某个对应的描述符即可。
特性 | 属性值 | 说明 |
---|---|---|
App Widget | android.software.app_widgets |
应用程序使用或提供了 App Widget,并且只能安装到提供主屏幕或类似地方的设备上, 用户可以在这个地方嵌入多个 App Widget。 |
设备管理 | android.software.device_admin |
应用程序通过设备管理器使用设备强制策略。 |
主屏幕 | android.software.home_screen |
应用程序可替代主屏幕运行,且仅能在支持第三方主屏幕应用的设备上安装。 |
输入手段 | android.software.input_methods |
应用程序提供了自定义的输入手段,且仅能在支持第三方输入手段的设备上安装。 |
活动壁纸 | android.software.live_wallpaper |
应用程序用到或提供活动壁纸功能,且仅能在支持活动壁纸的设备上安装。 |
SIP/VOIP | android.software.sip |
应用程序用到 SIP 服务,且仅能在支持 SIP 的设备上安装。 |
android.software.sip.voip |
子特性。应用程序用到基于 SIP 的 VOIP 服务。 本特性隐含声明了父特性 |
上述表格中的某些特性常量只适用于对应版本 API 之后的应用; 例如,android.hardware.bluetooth
是从 Android 2.2 (API 级别 8)开始加入的, 但它引用的蓝牙 API 自 Android 2.0 (API 级别 5)开始就已经加入了。 因此,在可以通过 <uses-feature>
系统声明 API 需求之前,某些应用程序已经可以使用这些 API 了。
为了防止无意之中使用到这些应用程序, Google Play 假定某些硬件相关的权限默认就声明了相应底层硬件特性的需求。 举例来说,用到蓝牙的应用程序必然会在 <uses-permission>
元素中请求 BLUETOOTH
权限 — 对于老版本的应用, Google Play 就假定此权限声明意味着应用程序需要底层的 android.hardware.bluetooth
特性, 并会建立基于此特性的过滤机制。
下表列出了隐含了特性需求的权限,等同于这些特性已经在 <uses-feature>
元素中声明了。 请注意, <uses-feature>
的声明(包括所有带有 android:required
属性的声明) 总是优先于下述权限隐含的特性需求。
下述所有的权限,都可以禁用基于隐含声明的过滤行为, 这通过声明附带 android:required="false"
属性的 <uses-feature>
元素来实现。 例如,为了禁用基于 CAMERA
权限的过滤行为,可以在 Manifest 文件中加入以下 <uses-feature>
声明:
<uses-feature android:name="android.hardware.camera" android:required="false" />
种类 | 权限 | 隐含的特性需求 |
---|---|---|
蓝牙 | BLUETOOTH |
android.hardware.bluetooth (详情请参阅 对蓝牙特性的特殊处理。) |
BLUETOOTH_ADMIN |
android.hardware.bluetooth |
|
摄像头 | CAMERA |
android.hardware.camera 和 android.hardware.camera.autofocus |
定位 | ACCESS_MOCK_LOCATION |
android.hardware.location |
ACCESS_LOCATION_EXTRA_COMMANDS |
android.hardware.location |
|
INSTALL_LOCATION_PROVIDER |
android.hardware.location |
|
ACCESS_COARSE_LOCATION |
android.hardware.location.network 和 android.hardware.location |
|
ACCESS_FINE_LOCATION |
android.hardware.location.gps 和 android.hardware.location |
|
话筒 | RECORD_AUDIO |
android.hardware.microphone |
电话 | CALL_PHONE |
android.hardware.telephony |
CALL_PRIVILEGED |
android.hardware.telephony |
|
MODIFY_PHONE_STATE |
android.hardware.telephony |
|
PROCESS_OUTGOING_CALLS |
android.hardware.telephony |
|
READ_SMS |
android.hardware.telephony |
|
RECEIVE_SMS |
android.hardware.telephony |
|
RECEIVE_MMS |
android.hardware.telephony |
|
RECEIVE_WAP_PUSH |
android.hardware.telephony |
|
SEND_SMS |
android.hardware.telephony |
|
WRITE_APN_SETTINGS |
android.hardware.telephony |
|
WRITE_SMS |
android.hardware.telephony |
|
Wi-Fi | ACCESS_WIFI_STATE |
android.hardware.wifi |
CHANGE_WIFI_STATE |
android.hardware.wifi |
|
CHANGE_WIFI_MULTICAST_STATE |
android.hardware.wifi |