田海立@CSDN

翻译自Google Play and Feature-Based Filtering

GooglePlay会过滤出那些对用户可见的应用程序,因此用户只能看到和下载那些与他们的设备兼容的应用程序。过滤应用程序其中的一种方法就是通过Feature兼容性。

Google Play为判断应用程序与给定的用户设备是否兼容,比较:

  • 应用程序需要的Feature– 应用程序在它自己的manifest中通过<uses-feature>申明所需要的Feature;

  • 在设备上有效的硬/软件Feature-- 设备用只读的系统属性报告的它所支持的Feature。

为了确保Feature的准确比较,AndroidPackage Manager提供了一个共享的Feature常量集合,应用程序和设备都使用这些常量来声明各自所需要和支持的Feature。可用的Feature常量在本文下面的Feature参考表中被列出,它们定义在类文档PackageManager中。

当用户启动GooglePlay时,应用程序通过调用getSystemAvailableFeatures()方法,来查询包PackageManager中所列出的设备上可用的Featurelist。然后在建立用户会话的时候,软件商店(TheStore)应用程序会把这个Featurelist上传给GooglePlay。

每次把应用程序上传给GooglePlay的发布网站时,GooglePlay都会扫描应用程序的Manifest文件。它会查找Manifest中的<uses-feature>元素,并且在某些情况下,会把它们跟其他元素组合在一起来评估,如<uses-sdk><uses-permission>元素。在建立了应用程序所需的Feature集合之后,GooglePlay会把这个列表做为跟应用程序的.apk和版本相关联的内部元数据保存起来。

当用户使用GooglePlay应用程序查询或浏览应用商店里的应用程序时,服务就会把每个应用程序所需的Feature跟用户设备上可用的Feature进行比较。如果应用程序所需要的所有Feature在设备上都存在,那么GooglePlay就允许用户看到该应用程序,并潜在的可下载它。如果应用所需的任何一个Feature不被设备所支持,GooglePlay就过滤掉该应用程序,这样用户就看不到并且也不能够下载。

因为在<uses-feature>元素中声明的Feature直接影响到GooglePlay如何过滤应用程序,因此理解GooglePlay是如何评估应用程序的Manifest和建立需求Feature的集合是至关重要的,以下章节会详细说明。

基于明确声明Feature的过滤

一个明确声明的Feature就是应用程序声明的一个<uses-feature>元素。Feature声明可以包含一个android:required=["true"| "false"]的属性(如果在APILeve5或以上的版本上编译),这个属性指定了应用程序是否绝对的需要该Feature,如果目标设备上不存在该Feature,该应用程序就不能正常的运行("true"的场合),或指定应用程序偏好该Feature,在Feature有效的时候就使用该它,而在该Feature无效时,应用程序也被设计成也是可以运行的("false"的场合)。

Google Play用以下方法来处理明确声明的Feature:

  • 如果一个Feature被明确声明为必须的,那么GooglePlay就会把该Feature加入到该应用程序所需要的功能列表中。然后把应用程序从没有提供该应用所需Feature的设备中过滤掉。例如:

    <uses-feature android:name="android.hardware.camera" android:required="true" />
  • 如果一个Feature被明确声明为非必须的,GooglePlay就不会把这个的Feature添加到所需的Feature列表中。由于这个原因,明确声明的非必须的Feature,在GooglePlay过滤应用程序时就不会被考虑。即使设备不声明提供该Feature,GooglePlay依然会认为该应用程序与设备是兼容的,并允许显示给用户,除非使用了其他过滤规则。例如:

    <uses-feature android:name="android.hardware.camera" android:required="false" />
  • 如果一个Feature被明确声明,但没有设置android:required属性,那么GooglePlay就会假定该功能是必须的,并且要针对该功能进行过滤。(译者注:缺省是true)

通常,如果应用程序被设计成要运行在Android1.6或更早的版本上,那么在API中android:required属性是无效的,并且GooglePlay会假定<uses-feature>的申明都是必须的。

注意:通过明确声明一个Feature,并且包含android:required=”false”的属性,能够禁止GooglePlay针对该Feature的所有过滤。

基于隐式Feature的过滤

一个隐式的Feature是为了让应用程序正确运行所需的功能,但是,这个Feature并不在申明在Manifest的<uses-feature>元素中。严格来说,每个应用程序都应该始终声明它所使用和需要的所有Feature,因此对于应用程序使用的Feature,却没有声明,应该被认为是一个错误。但是,出于对用户和开发者的保护,GooglePlay会查看每个应用程序的隐式Feature,并基于这些Feature来建立过滤器,就像是对明确声明的Feature所做的处理一样。

应用程序可能需要一个Feature,但却没有声明,这是因为:

  • 应用程序是针对较旧的Android类库版本(Android1.5或更早)来编译的,当时<uses-feature>元素还是无效的;

  • 开发者错误的假定所需要的Feature在所有的设备上都存在,而认为没有必要声明;

  • 开发者不小心忽略的该Feature的声明;

  • 开发者明确的声明了该Feature,但该声明是无效的。例如:<uses-feature>元素名的一个拼写错误或给android:name属性设定一个无法识别的字符串,这些都会导致Feature声明的无效。

To account for the cases above, Google Play attempts to discoveran application's implied feature requirements by examining otherelements declared in the manifest file, specifically,<uses-permission>elements.基于以上原因的考虑,GooglePlay会尝试通过检查Manifest文件中其他元素(特别是<uses-permission>元素)的声明来发现被应用隐式需要的Feature。

如果一个应用程序申请了硬件相关的权限,那么GooglePlay就会假定应用程序要使用底层的硬件Feature,并因此而需要那些Feature,即使可能没有相应的<uses-feature>声明。针对这样的权限申请,GooglePlay也会把底层的硬件Feature添加到它所保持的对应的应用程序的元数据中,并基于这些信息来建立相应的过滤器。

例如,如果应用程序申请了CAMERA权限,但却没有声明一个<uses-feature>元素要求android.hardware.cameraFeature,那么GooglePlay就会认为应用程序需要照相机,并且该应用程序不应该显示给没有提供照相机功能的那些用户设备。

如果不想要GooglePlay基于某个特殊的隐式Feature来过滤应用程序,就要禁止这种行为。通过在<uses-feature>元素中明确的声明Feature,并包含一个android:required="false"属性,可以达到禁止GooglePlay过滤应用程序的目的。例如:要禁止由CAMERA权限所派生出来的过滤,就要像下面这样声明Feature:

<uses-feature android:name="android.hardware.camera" android:required="false" />

理解用<uses-permission>元素声明的权限能够直接影响GooglePlay对应用程序的过滤是至关重要的。在下面的权限隐含的Feature需求章节中,列出了所有的隐含的Feature需求的权限集,并因此而引发的过滤处理。

对于蓝牙Feature的特殊处理

当GooglePlay针对蓝牙功能来判断过滤时,它会使用比以上描述稍微不同的规则。

如果应用程序在其清单的一个<uses-permission>元素中声明了一个蓝牙权限,但没有明确的在<uses-feature>>元素中声明蓝牙Feature,那么GooglePlay会检查应用程序被设计成要运行在Android平台的哪个版本上,这个版本是在<uses-sdk>元素中被指定的。

如下表所示,GooglePlay只会在应用程序把Android2.0(APILeve5)或更高的版本作为最低版本或目标平台时,才会启用针对蓝牙功能的过滤。但是,要注意的是,当应用程序在<uses-feature>元素中明确声明了蓝牙Feature时,GooglePlay会使用普通的规则来进行过滤处理。

1:GooglePlay如何判断申请了蓝牙权限但却没有在<uses-feature>元素中声明蓝牙Feature的应用程序的蓝牙Feature需求的:

如果minSdkVersion

targetSdkVersion

结果

<=4 (或者uses-sdk没被申明)

<=4

对于任何报告其支持android.hardware.bluetoothFeature的设备,GooglePlay不会把应用程序过滤掉。

<=4

>=5

对于任何不支持android.hardware.bluetooth Feature的设备,GooglePlay都会把该应用程序过滤掉。

>=5

>=5

以下的例子,基于GooglePlay如何处理蓝牙Feature,演示了不同的过滤效果。

第一个例子中,应用程序被设计成要运行在比较旧的APILevel 上并声明了蓝牙权限,但是它没有在其 <uses-feature> 元素中声明蓝牙Feature 。
结果:GooglePlay 不会把该应用程序从任何设备上过滤掉。
<manifest ...>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-sdk android:minSdkVersion="3" />
    ...
</manifest>
第二个例子,相同的应用程序,还声明了一个目标APILevel 是5 的属性。
结果:GooglePlay 会假设应用程序需要蓝牙Feature ,并把应用程序从那些没有报告支持蓝牙功能的设备上过滤掉,包括那些运行较旧平台版本的的设备。
<manifest ...>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" />
    ...
</manifest>
这里,相同的应用程序,但声明的蓝牙Feature 需求。
结果:与第二个例子相同(过滤被应用)。
<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" 属性。
结果:GooglePlay 会针对所有设备禁止使用基于蓝牙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>

测试应用程序所需要的Feature

可以使用包含在AndroidSDK中的aapt工具,来判断GooglePlay会怎样过滤自己的应用程序(基于应用声明的Feature和Permission/权限)。用dump badging 命令来运行aapt工具,执行该项测试工作。aapt工具会解析应用程序的Manifest文件,并且使用与GooglPlay相同的规则,来判断应用程序所申请的Feature。

以下是使用这个工具的步骤:

  1. 首先,把应用程序作为一个未签名的..apk来编译并导出。如果使用带有ADT的Eclipse来开发应用程序,那么右击工程,并选择AndroidTools > Export Unsigned ApplicationPackage。选择目标文件名和路径,点击OK按钮。

  2. 接下来,如果在环境变量PATH中没有设置aapt的路径,定位找到它。如果使用的是SDK Toolsr8或更高的版本,那么可以在<SDK>/platform-tools/目录中找到aapt

    注意:所使用的aapt工具版本必须是提供给最新的可用的平台工具组件。如果没有,使用AndroidSDK Manager 来下载。

  3. 使用以下语法来运行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和基于Feature的过滤的更多相关文章

  1. Google Play和基于Feature的过滤 —— Feature 参考手册

    翻译自 Features Reference 下表列出了软/硬件Feature和权限的参考信息,它们被用于GooglePlay. 硬件feature 下面列出了被大多数当前发布的平台所支持的硬件功能描 ...

  2. 基于Feature Flag的下一代开发模式

    渐进式发布(Progressive Delivery)被认为是持续发布(Continous Delivery)的下一代形态,其专注于增强发布过程控制与降低发布风险,最终提高整体收益.国际科技巨头比如A ...

  3. gRPC:Google开源的基于HTTP/2和ProtoBuf的通用RPC框架

    gRPC:Google开源的基于HTTP/2和ProtoBuf的通用RPC框架 gRPC:Google开源的基于HTTP/2和ProtoBuf的通用RPC框架 Google Guava官方教程(中文版 ...

  4. Google机器学习课程基于TensorFlow : https://developers.google.cn/machine-learning/crash-course

    Google机器学习课程基于TensorFlow  : https://developers.google.cn/machine-learning/crash-course         https ...

  5. 基于AngularJS的过滤与排序

    前面了解了AngularJS的使用方法,这里就简单的写个小程序,实现查询过滤以及排序的功能. 本程序中可以了解到: 1 angularjs的过滤器 2 ng-repeat的使用方法 3 控制器的使用 ...

  6. 【AngularJS】—— 6基于AngularJS的过滤与排序

        阅读目录 程序设计分析 代码以及结果 前面了解了AngularJS的使用方法,这里就简单的写个小程序,实现查询过滤以及排序的功能. 本程序中可以了解到: 1 angularjs的过滤器 2 n ...

  7. Ecside基于数据库的过滤、分页、排序

    首先ecside展现列表.排序.过滤(该三种操作以下简称为 RSF )的实现原理完全和原版EC一样, 如果您对原版EC的retrieveRowsCallback.sortRowsCallback.fi ...

  8. 基于AngularJS的过滤与排序【转载】

    程序设计分析 首先,如果要是先查询过滤,就要使用到AngularJS中的 过滤器filter 了. 直接在表达式的后面使用管道命令符 | ,按照下面的写法就可以达到一个过滤的效果: {{ person ...

  9. 基于用户协同过滤--UserCF

    UserCF  本系列文章主要介绍推荐系统领域相关算法原理及其实现.本文以项亮大神的<推荐系统实践>作为切入点,介绍推荐系统最基础的算法(可能也是最好用的)--基于用户的协同过滤算法(Us ...

随机推荐

  1. NSURLSessionConfiguration的简单实用

    NSURLSessionConfiguration 基于前面学习了NSURLSession的知识,这边文章就讲下NSURLSessionConfiguration相关应用,(这名字可真长). 简而言之 ...

  2. STL模板_十大容器概念

    一.向量(续)1.大小和容量大小:容器中元素的个数.容量:容器中可容纳元素的个数.size_type size (void) const; // 获取大小void resize (size_type ...

  3. [非技术参考]C# Socket网络编程

    我们在讲解Socket编程前,先看几个和Socket编程紧密相关的概念: 1. TCP/IP层次模型 当然这里我们只讨论重要的四层 01,应用层(Application):应用层是个很广泛的概念,有一 ...

  4. mysql快速翻页查询方法

    SELECT SQL_NO_CACHE *FROM softdb_testWHERE id > (SELECT idFROM softdb_testORDER BY id DESCLIMIT 5 ...

  5. 智能电视TV开发---直播视频客户端结构设计和实现

    在智能电视TV开发---客户端和服务器通信里面我们实现了客户端和服务端的简单通信,接下来我们做一个简单的客户端界面,来实现手机端来操控智能电视的TV端. 一.存储视频的结构设计 我们在做客户端的时候, ...

  6. Django 探索(一) HelloWorld

    一.Django怎么读 酱狗 二.Django下载 安装 下载地址 安装: tar zxvf Django-1.5.4.tar.gz python setup.py install 三.建立一个Hel ...

  7. 公选网站作业4_2.php

    序:   此实验的功能是只有已经登陆或者已经注册的用户才有发表留言的资格,否则只能够浏览留言. 1.  主要文件: 4_2login.html// 登陆的主页面 4_2login.php  //处理登 ...

  8. codeforces 631C. Report

    题目链接 按题目给出的r, 维护一个递减的数列,然后在末尾补一个0. 比如样例给出的 4 21 2 4 32 31 2 递减的数列就是3 2 0, 操作的时候, 先变[3, 2), 然后变[2, 0) ...

  9. c#打印记忆功能

    下面这些实例都可以拷下直接用 总体思路:保存打印设置信息到本地文件,下次打印的时候直接读取文件信息,通过序列化与反序列化来获取值.本例只是针对打印的横纵向进行设置,读者也可以增加其他设置信息进行保存读 ...

  10. gdbserver 安卓apk

    gdbserver  调试程序 底层调用c/c++ 动态库, 动态库带调试选项 查看手机IP 192.168.1.177 包所调用的c/c++ 库是在/data/data/包名/lib/ 下 1.将安 ...