田海立@CSDN
html
翻譯自Google Play and Feature-Based Filteringandroid
GooglePlay會過濾出那些對用戶可見的應用程序,所以用戶只能看到和下載那些與他們的設備兼容的應用程序。過濾應用程序其中的一種方法就是經過Feature兼容性。app
Google Play爲判斷應用程序與給定的用戶設備是否兼容,比較:ide
應用程序須要的Feature– 應用程序在它本身的manifest中經過<uses-feature>
申明所須要的Feature;工具
在設備上有效的硬/軟件Feature-- 設備用只讀的系統屬性報告的它所支持的Feature。測試
爲了確保Feature的準確比較,AndroidPackage Manager提供了一個共享的Feature常量集合,應用程序和設備都使用這些常量來聲明各自所須要和支持的Feature。可用的Feature常量在本文下面的Feature參考表中被列出,它們定義在類文檔PackageManager
中。網站
當用戶啓動GooglePlay時,應用程序經過調用getSystemAvailableFeatures()
方法,來查詢包PackageManager中所列出的設備上可用的Featurelist。而後在創建用戶會話的時候,軟件商店(TheStore)應用程序會把這個Featurelist上傳給GooglePlay。ui
每次把應用程序上傳給GooglePlay的發佈網站時,GooglePlay都會掃描應用程序的Manifest文件。它會查找Manifest中的<uses-feature>
元素,而且在某些狀況下,會把它們跟其餘元素組合在一塊兒來評估,如<uses-sdk>
和<uses-permission>
元素。在創建了應用程序所需的Feature集合以後,GooglePlay會把這個列表作爲跟應用程序的.apk
和版本相關聯的內部元數據保存起來。spa
當用戶使用GooglePlay應用程序查詢或瀏覽應用商店裏的應用程序時,服務就會把每一個應用程序所需的Feature跟用戶設備上可用的Feature進行比較。若是應用程序所須要的全部Feature在設備上都存在,那麼GooglePlay就容許用戶看到該應用程序,並潛在的可下載它。若是應用所需的任何一個Feature不被設備所支持,GooglePlay就過濾掉該應用程序,這樣用戶就看不到而且也不可以下載。.net
由於在<uses-feature>
元素中聲明的Feature直接影響到GooglePlay如何過濾應用程序,所以理解GooglePlay是如何評估應用程序的Manifest和創建需求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並不在申明在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.camera
Feature,那麼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需求的權限集,並所以而引起的過濾處理。
當GooglePlay針對藍牙功能來判斷過濾時,它會使用比以上描述稍微不一樣的規則。
若是應用程序在其清單的一個<uses-permission>
元素中聲明瞭一個藍牙權限,但沒有明確的在<uses-feature>
>元素中聲明藍牙Feature,那麼GooglePlay會檢查應用程序被設計成要運行在Android平臺的哪一個版本上,這個版本是在<uses-sdk>
元素中被指定的。
以下表所示,GooglePlay只會在應用程序把Android2.0(APILeve5)或更高的版本做爲最低版本或目標平臺時,纔會啓用針對藍牙功能的過濾。可是,要注意的是,當應用程序在<uses-feature>
元素中明確聲明瞭藍牙Feature時,GooglePlay會使用普通的規則來進行過濾處理。
表1:GooglePlay如何判斷申請了藍牙權限但卻沒有在<uses-feature>元素中聲明藍牙Feature的應用程序的藍牙Feature需求的:
若是 |
或 |
結果 |
---|---|---|
<=4 (或者uses-sdk沒被申明) |
<=4 |
對於任何報告其支持 |
<=4 |
>=5 |
對於任何不支持 |
>=5 |
>=5 |
如下的例子,基於GooglePlay如何處理藍牙Feature,演示了不一樣的過濾效果。
<uses-feature>
元素中聲明藍牙Feature
。
<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"
屬性。
<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>
可使用包含在AndroidSDK中的aapt
工具,來判斷GooglePlay會怎樣過濾本身的應用程序(基於應用聲明的Feature和Permission/權限)。用dump badging
命令來運行aapt
工具,執行該項測試工做。aapt
工具會解析應用程序的Manifest文件,而且使用與GooglPlay相同的規則,來判斷應用程序所申請的Feature。
如下是使用這個工具的步驟:
首先,把應用程序做爲一個未簽名的..apk
來編譯並導出。若是使用帶有ADT的Eclipse來開發應用程序,那麼右擊工程,並選擇AndroidTools > Export Unsigned ApplicationPackage。選擇目標文件名和路徑,點擊OK按鈕。
接下來,若是在環境變量PATH中沒有設置aapt
的路徑,定位找到它。若是使用的是SDK Toolsr8或更高的版本,那麼能夠在<
SDK>/platform-tools/
目錄中找到aapt
。
注意:所使用的aapt
工具版本必須是提供給最新的可用的平臺工具組件。若是沒有,使用AndroidSDK 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'