转载自:http://blog.youkuaiyun.com/ccpat/article/details/51559168
uses-feature声明
AndroidManifest中的uses-feature配置用来声明一个app在运行时所依赖的外部的硬件或软件特征(feature),uses-feature还提供了一个required属性配置,表示此项依赖的软硬件特征是否是必须的,当它设置为true表示此app运行时必须使用此项特征,如果没有则无法工作,如果它设置为false,表示应用在运行时需要用到这些特征,但如果没有,应用可能会有一部分功能会受到影响,但大部分功能还是可以正常工作。例如一个拍照app,它使用时必须开启设备的摄像头,在没有摄像头的机器上任何功能都无法使用,这就需要通过uses-feature来声明该应用需要摄像头,并将required设置为true。再比如一个支付app,它支持扫码支付的功能,这项功能同样需要开启设备的摄像头,因此需要通过uses-feature声明该应用需要摄像头,但如果一个设备没有摄像头,仅意味着扫码支付的功能无法使用,其他支付方式仍然可以使用,这时就可以设置required属性为false,表明此项feature的需求不是必须的。
语法
<uses-feature android:name="string"
android:required=["true" | "false"]
android:glEsVersion="integer" />
- 1
- 2
- 3
- 1
- 2
- 3
所属节点
<manifest>
- 1
- 1
属性
Android:name
feature的名字。Android系统支持的feature可以通过 https://developer.android.com/guide/topics/manifest/uses-feature-element.html#features-reference 来查询。其中硬件特征的名字以android.hardware.为前缀,软件特征的名字以android.software.为前缀。
android:required
android:required属性表示这项feature是否是必须的,它的值只能是true或者false。如果设置为true表示这项feature是必须的,如果没有,应用将无法工作。如果设置为false,表示应用需要这项feature,但如果没有,可能会影响部分功能,但应用还是能够正常工作的。如果没有指定这项属性,则默认为true,即表示此feature是必须的。
android:glEsVersion
此项属性表示app所依赖的OpenGL ES的版本,它的值是一个整数,高16位表示OpenGL ES的大版本,低16位表示OpenGL ES的小版本。例如 OpenGL ES 3.2版本对应的整数值为0x00030002,完整配置如下。
<!-- Tell the system this app requires OpenGL ES 3.2. -->
<uses-feature android:glEsVersion="0x00030002" android:required="true" />
- 1
- 2
- 1
- 2
目前Android支持的OpenGL ES版本有1.0, 1.1, 2.0, 3.0, 3.1和 3.2。其中GLES 1.0从Android1.0开始支持,GLES 1.1从Android1.6开始支持,GLES 2.0从Android2.2 (API level 8) 开始支持,GLES 3.0从Android4.3(API level 18)开始支持,GLES 3.1从Android 5.0 (API level 21)开始支持,GLES 3.2则从Android N开始支持。OpenGL ES版本可以向下兼容,这意味着一个Android版本支持到某个OpenGL ES版本,同样可以支持更低的OpenGL ES版本。例如Android4.3支持到GLES 3.0,那么它也可以支持GLES 1.0到GLES 3.0之间的版本。因此可以得出各个Android版本支持的GLES版本区间如下。
| Android版本 | GLES版本 |
|---|---|
| Android1.0 - Android1.5 | GLES 1.0 |
| Android1.6 - Android2.1 | GLES 1.0 - GLES 1.1 |
| Android2.2 - Android4.2 | GLES 1.0 - GLES 2.0 |
| Android4.3 - Android4.4 | GLES 1.0 - GLES 3.0 |
| Android5.0 - Android6.0 | GLES 1.0 - GLES 3.1 |
| AndroidN - | GLES 1.0 - GLES 3.2 |
通常在AndroidManifest中应该只有一个android:glEsVersion配置,如果配置了多个,则只有版本号最大的那一个会生效,其他配置会被忽略。如果在AndroidManifest中没有配置android:glEsVersion,则表示可以支持到OpenGL ES 1.0,也就是所有的Android系统都支持。
uses-feature的作用
uses-feature只是对外提供了这样一组信息,表明它所依赖的软硬件特征,这个信息通常是给应用市场使用的,应用市场会读取app的uses-feature设置,然后只给那些满足这组软硬件特征的设备分发这个app。
Android系统在应用安装时并不会使用这里的信息。例如一个app在uses-feature中声明了需要摄像头,且required为true,那么应用市场在分发app时就不会将该app分发给那些没有摄像头的设备上,一个没有摄像头的设备也不能通过应用市场搜索和下载到该app。但是如果用户通过其他渠道(例如官网)下载该app对应的apk文件到某个设备上,在该设备上安装此apk时,系统并不会检查uses-feature所声明的软硬件特征是否满足,如果该设备没有摄像头,同样可以安装该app。
不仅如此,Android系统在应用运行时也不会使用这里的信息,所以uses-feature声明对应用的运行也不会产生影响(除非应用自己在代码中去判断某项feature是否满足)。这点和uses-permission是不一样的,Android系统会读取应用的uses-permission,并对应用的运行产生影响。同样以摄像头为例,如果应用某项功能需要用到摄像头,无论uses-feature如何声明,都不会影响到摄像头是否能够使用。虽然如果设备没有摄像头这个硬件,这项功能就无法使用,但是这和uses-feature声明无关。但如果没有通过uses-permission声明摄像头的权限,那么即使有摄像头硬件,也是无法使用摄像头的。
这里的因果关系是这样的:由于应用没有这项feature就无法工作,所以需要在AndroidManifest中配置uses-feature,让应用市场在分发app时自动过滤掉那些不支持的设备,不是由于配置了uses-feature,导致应用在没有这项feature的设备上无法工作。
Google Play app过滤机制
当用户打开Google Play浏览或查找应用时,Google Play会对用户可见的app进行过滤,用户在Google Play上只能够看到和下载到那些能够和用户设备相兼容的app。根据uses-feature声明的软硬件特征来过滤app是其中的一种方式。
当开发者上传apk文件到Google Play后,Google Play会读取apk文件中AndroidManifest,根据uses-feature,uses-sdk,uses-permission,uses-library等配置信息来评估此app所需要的features,然后根据这些信息生成一份元数据和该apk版本关联起来,保存到数据库中。
当用户打开设备上的Google Play应用时,Google Play应用会通过getSystemAvailableFeatures()获取到当前设备所支持的软硬件特征,然后将此列表发送给Google Play,之后当用户在这台设备上通过Google Play浏览或查找应用时,Google Play会将每个应用所需要的feature和用户设备支持的feature做比较。只有那些所有需要的feature在当前设备上都支持的app才会显示出来,如果一个app所需要的某个feature不能被当前设备满足,那么在这台设备上就不会显示这个app。
对Google Play审核的影响
Google Play要求app必须显式的声明所有需要的features,尤其是那些通过uses-permission可以推断出来的features。例如在uses-permission中声明了CAMERA权限,那么显然app需要使用摄像头,而如果这时又没有声明和摄像头有关的uses-feature,那么Google Play会认为app没有声明所有需要的features,可能会导致审核失败。
feature信息的代码表示
Android SDK中用FeatureInfo类来表示feature信息,它主要包含如下成员变量和方法。相关说明已经包含在注释中。
public class FeatureInfo implements Parcelable {
/**
* 此feature的名字,例如"android.hardware.camera"。
* 所有的feature除了OpenGL ES版本外都有一个对应的名字
* 这些名字可以在PackageManager类中找到对应的常量,都是以FEATURE_开头,
* 例如"android.hardware.camera"对应的常量是PackageManager.FEATURE_CAMERA。
* 对OpenGL ES版本featuer,这里的name的值是null
*/
public String name;
/**
* reqGlEsVersion的默认值
*/
public static final int GL_ES_VERSION_UNDEFINED = 0;
/**
* GLES版本,高16位表示GLES的大版本,低16位表示GLES的小版本。
* 只有在名字为null时才有效
*/
public int reqGlEsVersion;
/**
* 表示当前应用需要此feature
*/
public static final int FLAG_REQUIRED = 0x0001;
/**
* 表示当前应用是否需要此feature,可以是0或者FLAG_REQUIRED
*/
public int flags;
……这里省略了构造方法和序列化方法……
/**
* 将reqGlEsVersion转换为字符串格式的版本号,如0x00010002会返回1.2
*/
public String getGlEsVersion() {
int major = ((reqGlEsVersion & 0xffff0000) >> 16);
int minor = reqGlEsVersion & 0x0000ffff;
return String.valueOf(major)+"."+String.valueOf(minor);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
通过代码获取feature信息
正如前面所说,一个app配置的use-feature信息是给应用市场使用的,对app自身来说通常并不需要获取这些信息。不过如果确实需要这些信息,也是可以通过代码来获取的。
获取当前设备支持的所有features
FeatureInfo[] f = getPackageManager().getSystemAvailableFeatures();- 1
- 1
判断当前设备是否支持某项feature
boolean b = getPackageManager().hasSystemFeature(featureName);- 1
- 1
获取当前app的uses-feature配置
try { String packageName = getPackageName(); PackageInfo p = getPackageManager().getPackageInfo(packageName, PackageManager.GET_CONFIGURATIONS); FeatureInfo[] f = p.reqFeatures; } catch (NameNotFoundException e) { e.printStackTrace(); }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这里也可以用来获取当前设备上已经安装的其他app的uses-feature配置,只需要将packageName换成需要获取的app对应的包名即可。获取其他app的uses-feature配置不需要特别的权限,设备上已安装的任意一个app都可以获取。
本文详细介绍了AndroidManifest.xml中uses-feature元素的用途及配置方法,包括如何声明应用所需的硬件或软件特性,以及这些声明如何影响应用在Google Play上的分发。


1889

被折叠的 条评论
为什么被折叠?



