1. 程式人生 > >Android-0.使用 APK Analyzer 分析你的 APK

Android-0.使用 APK Analyzer 分析你的 APK

Android Studio包含了APK Analyzer,可在構建過程完成後立即深入瞭解APK的組成,使用APK Analyzer不僅能夠減少你花在debug上的時間,而且還能減少你的APK大小。 使用APK Analyzer,你可以完成以下操作:

  • 檢視APK中檔案的絕對大小和相對大小。(譯註:相對大小指的是該檔案佔整個APK大小的百分比)
  • 理解DEX檔案的組成。(譯註:能看到DEX檔案中包含了哪些類)
  • 快速檢視APK中檔案的最終版本(比如AndroidManifest.xml)。(譯註:AndroidManifest.xml、resources.arsc本來是二進位制形式顯示的,APK Analyzer能夠解析並顯示這些檔案的內容)
  • 對比兩個APK。(譯註:新版APK和舊版APK之間檔案大小的差異)

這裡有3種方法訪問APK Analyzer:

  • 拖拽APK到Android Studio的編輯器視窗中。
  • 切換到Project檢視,然後在預設的build/ouputs/apk/目錄下雙擊APK檔案。
  • 在選單欄中選擇Build > Analyzer APK,並且選擇APK。

注意:當使用APK Analyzer分析debug的APK,請使用Build > Build APK或gradle命令生成的APK。點選ToolBar中的Run將會生成Instant Run的APK。APK Analyzer不能分析通過Instant Run生成的APK,因為它們僅供開發使用,並動態載入大多數資源,判斷APK是否是Intant Run生成的可以通過看APK中是否有instant-run.zip檔案。

檢視檔案和大小資訊

APK就是一個zip包。APK Analyzer顯示每個檔案或目錄作為一個實體,實體的層級說明了APK檔案的結構。 如圖1,APK Analyzer對每個實體顯示了raw file size和download file size。Raw File Size表示實體在磁碟中解壓後的大小,而Download Size表示實體在Google Play中壓縮後的大小。% of Total Download Size表示實體的download size佔APK總的download size的百分比。

譯註:圖1中,最上面的1.4M是指APK在磁碟中的大小,而1.2M是指從Google Play中下載的大小。 在這裡插入圖片描述

圖1:在APK Analyzer中的檔案大小 譯註:通過檢視各個目錄或檔案的大小,我們能發現APK中哪個區域的檔案太大了,比如如果dex太大,我們是不是引入了重複功能的第三方庫(比如Glide和Fresco),或者抽取出一個精簡的第三方庫(精簡ffmpeg庫);如果res目錄太大,我們可以看看哪些圖片過大了,需要通過tinypng壓縮,或者用webp代替。

檢視AndroidManifest.xml

如果專案中包含了多個AndroidManifest.xml或者包含提供manifest檔案的library,在APK中他們將被合併為一個manifest檔案。在APK中manifest檔案是普通的二進位制檔案,但是在APK Analyzer中檢視manifest檔案,該檔案是以XML形式顯示的。這種顯示形式讓我們能理解應用中的任何變化。比如,你能看到library中的AndroidManifest.xml是怎麼合入最後的AndroidManifest.xml的。

另外,這種顯示形式提供了lint的能力,會在右上角顯示警告、錯誤提示。圖2顯示了manifest檔案的錯誤提示 圖2:manifest檔案的一個錯誤

檢視DEX檔案

APK Analyzer的DEX檔案瀏覽器讓你能夠快速瞭解DEX檔案的資訊。我們能看到類、包、總的引用和宣告個數,這些資訊能夠幫助我們決定是否使用multi-dex或者移除依賴使得滿足64K方法數限制。

圖5展示了一箇中等大小的APP(方法數接近64K)。每個包、類、方法都列有Defined Method和Referenced Method。Referenced Method列是DEX檔案中引用的全部方法,它包含了你定義的方法、依賴的library、定義在標準Java和Android包中的方法。Defined Method列只包含了定義在DEX檔案中方法,因此它是Referenced Method方法的子集。注意當你引入一個依賴,在依賴中定義的方法會包含在Defined Method和Referenced Method中。還要注意,混淆壓縮也會改變DEX檔案的內容。 在這裡插入圖片描述

過濾DEX檔案樹檢視

在“類別”列表上方,APK Analyzer提供了用於檢視所選DEX檔案內容的過濾器。 在這裡插入圖片描述 要使用過濾器顯示類中的所有方法和欄位,請執行以下操作:

  • 在File列表中,選擇classes.dex檔案。
  • 在class列表中,導航並選擇一個class
  • 展開class
  • 切換顯示fileds來顯示或隱藏class fileds
  • 切換顯示methods來顯示或隱藏class methods
  • 切換顯示所有引用methods或fileds來顯示或隱藏引用的packages,classes, methods和fileds,斜體節點是在所選DEX檔案中沒有定義的引用。 DEX檔案可以引用在不同檔案中定義的方法和欄位。 例如: System.out.println()是對Android框架中println()方法的引用。

載入Proguard對映

過濾圖示旁邊是Proguard對映圖示。 它們將顯示為灰色,直到您載入一組Proguard對映檔案,這些檔案向DEX檢視器新增功能,例如反混淆名稱(mapping.txt),顯示已刪除的節點(usage.txt)以及指示無法刪除的節點(seeds.txt)。 Proguard對映檔案適用於啟用Proguard的APK,並且必須和生成APK有相同的構建。 在這裡插入圖片描述

要載入Proguard對映檔案,請執行以下操作: 1.點選 Load Proguard Mappings. 2.導航到包含對映檔案的專案資料夾,並載入所有檔案,檔案的任意組合或包含這些檔案的資料夾。 對映檔案通常位於project/app/build/outputs/mappings/release/中。 如果檔案選擇器檢測到此專案結構,則預設為release資料夾。 首先,檔案選擇器檢查與mapping.txt,seeds.txt和usage.txt完全匹配的檔名。 接下來,檔案選擇器檢查包含文字對映,用法或種子的檔名,並以.txt結尾。 例如,release-seeds-1.10.15.txt是一個匹配項。

以下列表描述了對映檔案:

  • seeds.txt:Proguard配置阻止在收縮過程中被刪除的節點以粗體顯示。
  • mapping.txt:啟用反混淆名稱,以便您可以恢復由Proguard進行模糊處理的節點的原始名稱。 例如,您可以將模糊的節點名稱(如a,b,c)還原為MyClass,MainActivity和myMethod()。
  • usage.txt:啟用Show removed節點,以便顯示Proguard在收縮期間刪除的類,方法和欄位。 已恢復的節點以刪除線顯示。 有關使用Proguard來混淆和最小化程式碼的更多資訊,請參閱Shrink your code and resources.

顯示位元組碼,查詢用法,並生成Keep規則

在這裡插入圖片描述 Show Bytecode:反編譯選中的class,method或fileds,並在對話方塊中顯示smail(非Java程式碼)位元組碼. Find usages: 顯示DEX程式碼的哪些其他部分對所選類或方法的引用(圖7)。 如果載入了seeds.txt,則以粗體顯示的節點表示Proguard配置會阻止它們在收縮期間被刪除: 在這裡插入圖片描述 Generate Proguard Keep rule: 顯示Proguard規則,您可以複製並貼上到專案Proguard配置檔案中,以防止在Proguard收縮階段刪除給定的包,類,方法或欄位(圖8)。 有關更多資訊,請參閱 Customize which code to keep.

檢視程式碼和資源實體

不同的構建任務會改變APK檔案最後的實體。比如混淆壓縮規則能改變你最後的程式碼和圖片資源。在APK Analyzer中能夠快速檢視檔案的最終版本:點選實體,就能在下面看到檔案的內容,包含文字和圖片實體的預覽。 圖3:最終圖片資源的預覽

APK Analyzer也能展示文字或二進位制檔案。比如點選resources.arsc能夠讓你看到針對配置特定的值(例如一個字串資源的特定語言的翻譯)。如圖4,你能看到每個字串資源的翻譯。 圖4:翻譯的字串資源預覽

比較APK檔案

APK Analyzer能比較兩個不同APK中各個實體的大小。這對於我們瞭解為何你的APP相比上個版本變大了是很有用的。

在釋出一個新版APK之前,在APK Analyzer中匯入你即將釋出的APK。在右上角點選Compare With,選擇上一個版本的APK,點選OK。然後就會出現類似圖的對話方塊,允許你比較之間的差別。

下圖顯示了一個APP的debug和release包的差別,不同的編譯型別會導致實體的不同。 在這裡插入圖片描述