Android碎片化全球一共有多少款Android設備呢?在Google App Store注冊在案的數(shù)據(jù),截止2016年8月5日,總計有12,518款不同的Android設備型號,這里還沒包括幾年前中國山寨廠商Android設備。同樣的,專業(yè)調研機構OpenSignal在2015年08月調研發(fā)現(xiàn)15年已經(jīng)發(fā)現(xiàn)24,093種Android設備,來自1,294個設備制造商。Android設備型號總量這個數(shù)字,每天都在增長。這個圖展示了從2014年08月到2015年同期,Android設備王國的演變,每個小方塊代表了一個設備的市場份額。
 Android Fragmentation report from OpenSignal
接觸過Android開發(fā)的人也許遇到,或者想到過,拿到一臺Android設備,如何能夠得到它在市場售賣時候的設備型號名稱,進而獲得詳細的設備參數(shù)信息(例如屏幕大小,CPU,RAM多少等等)。
打開Android系統(tǒng)的“設置”->“關于手機”,可以看到設備的基礎信息,其中有型號一欄。對于一部分手機,型號名和市場名是一致或者接近的,但有相當一部分設備的型號名和市場叫法沒有關聯(lián)很小,甚至任何關系。例如華為Mate7在系統(tǒng)中的型號名是HUAWEI MT7-CL00,一般人很難聯(lián)想到華為的Mate7;三星同一款市場叫法的手機,在不同國家發(fā)行其模型名不一樣,Galaxy Note4在中國發(fā)行的版本的型號名是SM-N9108V,筆者在第一次拿到這款設備的時候,如果不看包裝盒,幾乎無法從系統(tǒng)中獲取到該手機的市面叫法。
筆者最近在開發(fā)Appetizer.io時遇到一個需求,需要根據(jù)adb能獲取到的Android設備數(shù)據(jù),得到設備的樣例圖片和市場名。這種類似的需求場景,在Android相關的開發(fā)中有可能碰到,筆者在此分享一下實現(xiàn)該需求的思路與方法。
Android設備型號相關參數(shù)在Android系統(tǒng)的根目錄下,有文件 /system/build.prop ,這個文件是Android系統(tǒng)構建時產(chǎn)生的,描述了系統(tǒng)軟件和設備硬件相關的名稱和參數(shù)。Android系統(tǒng)所有獲取這些參數(shù)的API的根源,都是從這個文件獲取。
下面一段,是通過 adb shell 獲取的 小米4LTE 型號手機 /system/build.prop 中的部分內容。從中可以看出,小米的 ro.product.model 描述與市面叫法接近, ro.product.name 和 ro.product.device 類似昵稱,通常是內部開發(fā)代號, ro.product.brand 和 ro.product.manufacturer 分別指品牌和代工商,對于小米來說都是 Xiaomi ,存在一些設備的品牌和代工商是不同公司,例如Google的Nexus系列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| weilundeMacBook-Pro:~ azard$ adb shell shell@cancro:/ $ cat /system/build.prop | grep ro.product ro.product.model=MI 4LTE ro.product.brand=Xiaomi ro.product.name=cancro ro.product.device=cancro ro.product.board=MSM8974 # ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete, # use ro.product.cpu.abilist instead. ro.product.cpu.abi=armeabi-v7a ro.product.cpu.abi2=armeabi ro.product.cpu.abilist=armeabi-v7a,armeabi ro.product.cpu.abilist32=armeabi-v7a,armeabi ro.product.cpu.abilist64= ro.product.locale=zh-CN # ro.build.product is obsolete; use ro.product.device ro.product.manufacturer=Xiaomi ro.product.cuptsm=XIAOMI|ESE|02|01
|
這里插一段花絮,在被root的Android系統(tǒng)中, /system/build.prop 可以被修改。有些手機游戲的活動只針對特定型號的設備,當年《爐石傳說》有三星Galaxy手機專用卡背,玩家可以通過運行在PC上的Android模擬器,生成指定的 build.prop ,偽造成三星Galaxy手機獲得游戲卡背。
 Samsung special bonus
獲取設備外觀圖片如何從互聯(lián)網(wǎng)得到一部手機的外觀圖片,通過搜索引擎當然是最好的辦法。但根據(jù)adb能夠得到的數(shù)據(jù),準確的查找到一張手機的外觀圖,最好的方法還是使用專業(yè)的圖片庫。
筆者在網(wǎng)絡上爬行,發(fā)現(xiàn)了移動設備數(shù)據(jù)庫DeviceAtlas,這個庫收錄了各種型號的移動設備的硬件參數(shù),但監(jiān)獄該庫收錄的設備型號并不完全,例如三星只在某些國家發(fā)型的型號沒有收錄,而且很多設備沒有外觀圖片,因此放棄使用該庫作為設備外觀圖片的來源。
GSMArena是一個偏向媒體性質的網(wǎng)站,同樣收錄了各種型號的移動設備,從數(shù)量上GSMArena沒有收錄完全一種設備在各種國家發(fā)售的型號,但是該網(wǎng)站的設備外觀圖片覆蓋面廣且清晰。最終選擇使用此網(wǎng)站作為圖片源,復用GitHub上的開爬蟲項目gsmarenacrawler,將所有的設備圖片全都爬到本地,外觀圖片名并非 /system/build.prop 中的任何一項,而是接近市場大眾的通俗叫法,我們定義為 市場名 。
獲取設備市場名若要從 /system/build.prop 的信息映射到圖片名,首先要得到一臺設備的市場通俗叫法。鑒于之前提到的,很多設備的型號名,設備名與市場叫法沒有任何聯(lián)系,這一步必須使用外部數(shù)據(jù)表幫助建立映射。
GitHub上維護的開源項目AndroidDeviceNames滿足了這個需求場景,提供了嵌入Android的SDK直接獲取設備的市場名,可以用于一些需要顯示市場名的App上。這個項目實際上是存儲了一個大型的從 /system/build.prop 映射到設備市場名的 json 格式的數(shù)據(jù)結構。但是考慮到這是私人維護的項目,設備不一定齊全,也不一定能保證持續(xù)更新,需要更加權威的數(shù)據(jù)。
好在Google提供了使用在Google Play的設備市場名數(shù)據(jù)表格,來源是手機開放聯(lián)盟的注冊信息(鏈接1,鏈接2)。表格中有四列,是每臺注冊設備的 ro.product.manufacturer ,ro.product.model ,ro.product.device ,以及市場通俗名。表格中的三星Galaxy Note4就有二十多個不同的型號,應該是最權威的收錄。
這樣,就得到了一個 [ro.product.device, ro.product.model] --> market_name 的大表。
市場名與圖片的模糊匹配Google的表中的市場名,與GSMArena的圖片名在內容和格式上有些許不同,需要進行模糊匹配。筆者根據(jù)特征做了如下操作:
- 圖片名對中擴線,下擴線和空格進行切分,數(shù)字和字母切分開,字母統(tǒng)一轉成小寫,對于每個圖片名得到字符串數(shù)組
listA
- 市場名對空格進行切分,數(shù)字和字母切分,字母統(tǒng)一轉成小寫,加上品牌名,對于每個市場名得到字符串數(shù)組
listB
- 將每個圖片名的字符串數(shù)組
listA 與市場名 listB 進行配對,進行如下算法
1 2 3 4 5 6 7 8
| score = 0.0; count = 0; for market_word in listB: for pic_word in listA: if (market_word.find(pic_word)): count += 1; break; score = count / len(listB)
|
對于每個市場名,得分最高的圖片名即為該模糊匹配算法的最佳匹配項。
這樣得到了 market_name --> picture 的大表,與之前得到的表結合,最終得到了兩張表:
[ro.product.device, ro.product.model] --> market_name
[ro.product.device, ro.product.model] --> picture
通過這兩張表,就可以根據(jù) /system/build.prop 中的信息得到設備的市場名和外觀圖片。目前,如果用json格式存儲這兩張大表,未壓縮的情況下大概需要3MB的空間,當然gzip一下之后會變得超級小。
AppetizerIO的多設備控制工具里的這些設備信息,就是從這個設備數(shù)據(jù)庫來的:
 AppetizerIO devicectl screenshot
|