> Analyze APK...路徑下,點(diǎn)擊后可以選擇目標(biāo)路..."/>
您好,登錄后才能下訂單哦!
大家都知道,Android Studio
開發(fā)工具自帶了Analyze Apk
,可以很方便的分析Apk文件。具體位于菜單build >> Analyze APK...
路徑下,點(diǎn)擊后可以選擇目標(biāo)路徑下的Apk文件,甚至可以直接將目標(biāo)APK文件直接拖拽到Android Studio
中,不到幾秒中時(shí)間,馬上就會(huì)生成對(duì)應(yīng)的分析結(jié)果。
例如,微信Apk分析結(jié)果是這樣的:
又如,支付寶Apk分析結(jié)果:
瞬間感覺自己很niubility,有沒有?
有時(shí)候,我們也經(jīng)常用它來分析自己的Apk,例如,生成的安裝包到底長(zhǎng)什么樣子,里面的資源/代碼構(gòu)成,Manifest
中配置是否如預(yù)期,又或者方法數(shù),等等。但是,一次突然的機(jī)會(huì),發(fā)現(xiàn)自己開發(fā)的Ap分析不了,一直處于Parsing Manifest
狀態(tài)。
一臉懵逼,有木有?
這個(gè)問題曾經(jīng)困惑了我不少時(shí)間,之前也沒有具體去研究過。現(xiàn)在又遇到了。瞬間想到魯迅說的一句話:
技術(shù)路上,會(huì)遇到很多看似莫名其妙的問題,細(xì)心探究,解決了,就是成長(zhǎng)。
無視它并避讓過去,看似繞過了問題,實(shí)際上失去了一次很好的技術(shù)歷練的機(jī)會(huì),
并且下次很可能還會(huì)遇到類似的,甚至一樣的問題,長(zhǎng)期看將是困難和停滯。
既然先輩都這樣說了,那就,那硬著頭皮解一下?
現(xiàn)在給人的感覺是Analyze APK
執(zhí)行過程中直接停住了,后者長(zhǎng)時(shí)間一直在分析。但不管怎樣,畢竟是在AS中的操作,先查一下對(duì)應(yīng)的AS日志,看看有沒Parsing Manifest
或相關(guān)的日志信息,可以起到幫助的。
Help >> Show Log in Finder
,打開日志,對(duì)應(yīng)時(shí)間點(diǎn)看了又看,沒找到Parsing Manifest
直接相關(guān)的,不過,找到了控件顯示先關(guān)的日志:
2019-08-08?19:21:25,323?[entQueue-0]???INFO?-?ools.idea.apk.viewer.ApkEditor?-?Disposing?ApkEditor?with?ApkViewPanel:?com.android.tools.idea.apk.viewer.ApkViewPanel@7a608115?2019-08-08?19:21:25,323?[entQueue-0]???INFO?-?s.idea.apk.viewer.ApkViewPanel?-?Cleared?Archive?on?ApkViewPanel:?com.android.tools.idea.apk.viewer.ApkViewPanel@7a608115
從日志里面可以看出來,AS中對(duì)應(yīng)的Analyze Apk
相關(guān)的類名有ApkEditor
、ApkViewPanel
,包名是com.android.tools.idea.apk.viewer
。AS日志部分的有效信息只有這么多了。
AS日志中沒有,那有沒有可能存在有效的信息輸出在了系統(tǒng)其它的地方?于是,直接花點(diǎn)時(shí)間,系統(tǒng)全局搜索下。
/?grep?-rnl?"Parsing?Manifest"?*
輸出信息中有一些警告信息之類的,最終在輸出信息中找到了個(gè)相關(guān)的:
Applications/Android?Studio.app/Contents/plugins/android/lib/android.jar
看目錄名,大概是AS插件中對(duì)應(yīng)的Android相關(guān)的lib工具包。找到對(duì)應(yīng)位置,用JD-GUI打開對(duì)應(yīng)的jar文件,具體看下一下。
通過全局搜索關(guān)鍵字Parsing Manifest
,的確可以定位到具體的ApkViewPanel
類,且包名與上面AS日志中都能對(duì)的上,但字節(jié)碼反解成java過程中有內(nèi)部錯(cuò)誤。嘗試著用用jadx打開,因?yàn)閍ndroid.jar包還挺大,時(shí)間比較長(zhǎng),、最終雖然ApkViewPanel
部分內(nèi)容可以顯示,但內(nèi)部依然有部分內(nèi)部錯(cuò)誤無法顯示,且Parsing Manifest
不能直接顯示。
不過沒關(guān)系,我們?cè)囍フ艺以创a看看。搜索對(duì)應(yīng)包名:com.android.tools.idea.apk.viewer
,選擇java類別,很快,我們找到了對(duì)應(yīng)的源碼位置。
github.com/JetBrains/a…
正好,AS就是JetBrains主導(dǎo)的產(chǎn)品,Perfect!
很快,我們找到了對(duì)應(yīng)Parsing Manifest
的位置:
setAppInfo()
方法中,將對(duì)應(yīng)的控件內(nèi)容從原來的Parsing Manifest
改成了對(duì)應(yīng)的包名和版本號(hào)等信息。
顯然,在代碼myNameComponent.append("Parsing Manifest");
與setAppInfo(result);
之間,程序出了問題。
這之間關(guān)鍵的類,主要有apkParser
對(duì)象對(duì)應(yīng)的ApkParser
類,還有Archives
類。繼續(xù)跟蹤ApkParser
類,發(fā)現(xiàn)其主要也是一個(gè)外殼性質(zhì)的類,apkParser.constructTreeStructure()
方法主要流程來到如下所示位置:
現(xiàn)在,我們發(fā)現(xiàn),無論是此處的ArchiveTreeStructure
類,還是之前的Archives
類,這兩個(gè)關(guān)鍵線索上的類都不是在這個(gè)項(xiàng)目中。根據(jù)代碼文件中的import
導(dǎo)入,很快,我們發(fā)現(xiàn),線索被定向到了com.android.tools.apk.analyzer
包中。
從包名上來看,com.android.tools.apk.analyzer
應(yīng)該是Android Tools
中帶的一個(gè)工具。來到項(xiàng)目iml
文件,我們發(fā)現(xiàn)與之相關(guān)的構(gòu)件。其中,組名是:com.android.tools.apkparser
,構(gòu)件名是:apkanalyzer
。
至此,我們先總結(jié)下問題的原因。
AS中自帶的Analyze APK,實(shí)際上是通過集成了插件實(shí)現(xiàn),而插件內(nèi)部,又通過調(diào)用了 Android Tools中的名叫apkanalyzer
的工具實(shí)現(xiàn)的分析。因此,想要追溯出現(xiàn)問題的原因,我們需要再去對(duì)應(yīng)追蹤下apkanalyzer
。
如果熟悉Android Tools,我們對(duì)應(yīng)去tools目錄下找找,很快便能找到apkanalyzer
。及時(shí)不熟悉,不知道目錄位置也沒關(guān)系,打不了全局搜索下。
終于,對(duì)應(yīng)的工具本體出現(xiàn)在我們面前。
實(shí)際上,如果對(duì)Google Developer比較熟悉,或者直接在上面搜索下,也能直接在Analyze APK
頁面上找到核心信息,直接指向工具本體—apkanalyzer
。
developer.android.com/studio/buil…
啊哈,饒了半天,原來官方文檔上直接有啊,哭了,有木有?
同樣的,通過反編譯工具查看apkanalyzer.jar
代碼終究不太方便,且內(nèi)部也有不少INNER ERROR
。于是,我們繼續(xù)去GitHub上找找。
GitHub上搜索到的apkanalyzer
相關(guān)的零零散散,好像都是個(gè)人的,不太官方,也不符合我們的預(yù)期。怎么辦呢?
源碼不夠,Google Source來湊!
直接Google Source搜索可能的關(guān)鍵字,馬上得到了結(jié)果。
顯然,這正是我們需要的。
但此時(shí),如果直接源碼跟蹤下去,還是有難度的。
apkanalyzer
作為一個(gè)工具,是獨(dú)立的。在實(shí)際使用時(shí)可以直接脫離AS環(huán)境,Google Developer官網(wǎng)上也有專門的篇幅進(jìn)行了介紹。
developer.android.com/studio/comm…
實(shí)際使用時(shí),我們通過不同的命令行命令及參數(shù),可以得到我們期望的結(jié)果,如用來分析APK基本屬性,Manifest,dex或資源等。
由此,我們可以多試幾個(gè),反正AS中Analyze APK
最終用的也是它。在一定的命令上,結(jié)果肯定是一樣的。也就是說,通過命令行直接執(zhí)行apkanalyzer
,肯定也會(huì)有問題,但有個(gè)好處時(shí),命令行執(zhí)行往往都能拋出對(duì)應(yīng)的錯(cuò)誤日志。
有了進(jìn)一步的錯(cuò)誤日志提示,就有了異常棧和關(guān)鍵性的真正的錯(cuò)誤原因信息。
那我們就試一試吧。
???bin?apkanalyzer?-h?apk?file-size?Corn-dev-debug.apk 46.9MB ???bin?apkanalyzer?apk?summary?Corn-dev-debug.apk com.corn????10300???10.3.0.0 ???bin?apkanalyzer?manifest?print?Corn-dev-debug.apk<?xml?version="1.0"?encoding="utf-8"?><manifest ????xmlns:android="http://schemas.android.com/apk/res/android" ????android:versionCode="10300" ????android:versionName="10.3.0.0" ????package="com.mymoney" ????platformBuildVersionCode="27" ????platformBuildVersionName="8.1.0"> ????<uses-sdk ????????android:minSdkVersion="19" ????????android:targetSdkVersion="26"?/> ????<uses-permission ????????android:name="android.permission.GET_ACCOUNTS" ????????android:maxSdkVersion="22"?/>... ... ...
說明直接分析Manifest文件都是沒有問題的。
???bin?apkanalyzer?dex?list?Corn-dev-debug.apkclasses7.dexclasses6.dexclasses5.dexclasses4.dexclasses3.dexclasses2.dexclasses.dex復(fù)制代碼
???bin?apkanalyzer?resources?configs?--type?drawable??Corn-dev-debug.apk anydpi-v21 anydpi-v26 default watch-v20 v21 v23 ldpi-v4 mdpi-v4 ldrtl-mdpi-v17 hdpi-v4 ldrtl-hdpi-v17 xhdpi-v4 ldrtl-xhdpi-v17 xxhdpi-v4 ldrtl-xxhdpi-v17 xxxhdpi-v4 ldrtl-xxxhdpi-v17
???bin?apkanalyzer?files?list?Corn-dev-debug.apk Exception?in?thread?"main"?java.util.zip.ZipError:?invalid?END?header?(bad?central?directory?offset) ????at?com.sun.nio.zipfs.ZipFileSystem.zerror(ZipFileSystem.java:1605) ????at?com.sun.nio.zipfs.ZipFileSystem.initCEN(ZipFileSystem.java:1045) ????at?com.sun.nio.zipfs.ZipFileSystem.<init>(ZipFileSystem.java:130) ????at?com.sun.nio.zipfs.ZipFileSystemProvider.newFileSystem(ZipFileSystemProvider.java:117) ????at?java.nio.file.FileSystems.newFileSystem(FileSystems.java:326) ????at?java.nio.file.FileSystems.newFileSystem(FileSystems.java:276) ????at?com.android.utils.FileUtils.createZipFilesystem(FileUtils.java:538) ????at?com.android.tools.apk.analyzer.Archives.openInnerZip(Archives.java:48) ????at?com.android.tools.apk.analyzer.ArchiveTreeStructure.create(ArchiveTreeStructure.java:100) ????at?com.android.tools.apk.analyzer.ArchiveTreeStructure.create(ArchiveTreeStructure.java:65) ????at?com.android.tools.apk.analyzer.ApkAnalyzerImpl.filesList(ApkAnalyzerImpl.java:803) ????at?com.android.tools.apk.analyzer.ApkAnalyzerCli$Action$6.execute(ApkAnalyzerCli.java:430) ????at?com.android.tools.apk.analyzer.ApkAnalyzerCli.run(ApkAnalyzerCli.java:163) ????at?com.android.tools.apk.analyzer.ApkAnalyzerCli.main(ApkAnalyzerCli.java:130)
終于,在用命令顯示Apk內(nèi)所有文件列表的時(shí)候出現(xiàn)了問題。并且有對(duì)應(yīng)的調(diào)用棧信息拋出。
從調(diào)用棧中我們發(fā)現(xiàn),命令行的調(diào)用方式,是通過ApkAnalyzerCli
中的main
方法去接收命令參數(shù)的。在ApkAnalyzer.jar
同級(jí)的目錄中,我們發(fā)現(xiàn)了有對(duì)應(yīng)的ApkAnalyzerCli.jar
,其作用,就是基于ApkAnalyzer.jar
基礎(chǔ)上封裝的一個(gè)Client
,以方便程序被外部調(diào)用執(zhí)行,如通過命令行的方式等。
并且,突然間發(fā)現(xiàn),此處的棧信息與之前GitHub上JetBrains/android項(xiàng)目中分析到的源碼位置相同~??!
at?com.android.tools.apk.analyzer.ArchiveTreeStructure.create(ArchiveTreeStructure.java:100)
看來,這就是真實(shí)的原因所在了。
ArchiveTreeStructure
主要作用是分析apk文件中的檔案文件樹形結(jié)構(gòu),且從最終拋出的錯(cuò)誤信息可以看出:Apk包中zip文件出現(xiàn)的問題,zip文件頭部信息無效。
java.util.zip.ZipError:?invalid?END?header?(bad?central?directory?offset)
抓住這一關(guān)鍵點(diǎn),那就好辦了。直接搜索整個(gè)項(xiàng)目中的.zip
文件,發(fā)現(xiàn)還真有不少。并且存在于assets目錄下。主要存放的是一些資源。
直接解壓縮.zip文件,發(fā)現(xiàn)有問題,果然,此處有問題的.zip文件導(dǎo)致apkanalyzer在分析Apk過程中,分析到這些.zip文件出現(xiàn)了問題。
.zip格式顯然是不符合.zip規(guī)范的,那么,具體是什么問題呢?
查找到項(xiàng)目使用到這些文件的代碼位置。
淚奔了,有木有?!
到現(xiàn)在位置,整體邏輯已經(jīng)很清晰了。項(xiàng)目中因?yàn)榇嬖谝瞥吮硎緕ip格式的頭字節(jié)的zip文件,導(dǎo)致在使用Android Studio Analyze APK
分析Apk時(shí),出現(xiàn)程序錯(cuò)誤,從而只顯示Parsing Manifest
。
究竟對(duì)不對(duì)呢,可以以簡(jiǎn)單方式核驗(yàn)下。
1,通過移除此類有問題的.zip文件,重新打包,發(fā)現(xiàn)可以使用Android Studio Analyze APK
進(jìn)行分析了,直接使用apkanalyzer
命令行分析時(shí),也木有問題。
2,使用二進(jìn)制修改工具,將這類有問題的.zip文件對(duì)應(yīng)的四個(gè)字節(jié)的頭信息給補(bǔ)上。
此處推薦使用 Hex Friend 工具,可以直接以十六進(jìn)制修改對(duì)應(yīng)的二進(jìn)制文件內(nèi)容。
Hex Friend打開zip文件后,發(fā)現(xiàn)文件頭字節(jié)中,確實(shí)不符合zip規(guī)范。zip文件頭四個(gè)字節(jié)是固定的,504B0304
,用來表示的是對(duì)應(yīng)的zip格式。
于是,我們手動(dòng)補(bǔ)上試試。保存后,發(fā)現(xiàn).zip文件可以通過系統(tǒng)工具解壓了。
替換后再次打包驗(yàn)證,發(fā)現(xiàn)可以Android Studio Analyze APK
可以正常分析,apkanalyzer
可以直接使用。
項(xiàng)目中之所以此處將zip文件頭四個(gè)字節(jié)去除存放,當(dāng)時(shí)主要考慮是安全性問題。然后通過代碼的形式在拷貝過程中,去補(bǔ)上對(duì)應(yīng)的字節(jié)信息,相當(dāng)于進(jìn)行了修正。
現(xiàn)在既想不影響原有邏輯,同時(shí)又能愉快的使用Android Studio Analyze APK
進(jìn)行分析,怎么辦呢?
通過分析,我們發(fā)現(xiàn),apkanalyzer
拋出的異常,是在對(duì)zip文件進(jìn)行分析的時(shí)候出現(xiàn)的,那換一種思路,如果這類文件本身,不是zip文件格式,程序很可能就不會(huì)執(zhí)行到zip文件的分析判斷上,是不是就可以了呢?
說干就干,直接將項(xiàng)目中此類非規(guī)范化的zip文件格式替換,例如替換成一種自己隨意想的格式,就叫.tfc
吧,試試。
果然,再次打包,分析,OK,完全木有問題!
其實(shí)從反面來想,如果我們不想別人通過apkanalyzer
來分析我們的Apk,可以通過此類技巧,直接放一個(gè)不符合規(guī)范的zip文件在assets目錄中。例如本文中的將zip文件頭四個(gè)字節(jié)去除。
如果自己想分析自己的Apk,加對(duì)應(yīng)的文件移除即可。這樣在一定程度上,防防一些開發(fā)者,提高一下安全的門檻,還是可以的。
是不是有點(diǎn),尬?
apkanalyzer
是Android開發(fā)過程中,用來分析Apk中很有用的一個(gè)工具,經(jīng)常被用到。因?yàn)槠浼稍贏S中后,足夠簡(jiǎn)單輕便,且能一定程度上滿足我們分析Apk的需要。
項(xiàng)目在不斷的迭代,維護(hù)和開發(fā),項(xiàng)目中的技術(shù)問題也會(huì)不時(shí)出現(xiàn),對(duì)每一個(gè)技術(shù)問題,尤其是一些偏向于“疑難雜癥”性的技術(shù)問題,其實(shí)都是一次很好的技術(shù)歷練機(jī)會(huì)。認(rèn)真分析,不斷探因,最終會(huì)終有所獲。
一般的產(chǎn)品開團(tuán)隊(duì),面對(duì)這類問題,往往習(xí)慣的選擇繞開,因?yàn)樵诜敝氐男枨箝_發(fā)過程中,無暇此顧。其實(shí),對(duì)整個(gè)項(xiàng)目組來說,長(zhǎng)期來看,這是一個(gè)嚴(yán)重的問題。這類技術(shù)性問題,就像廚房中的小強(qiáng),如果發(fā)現(xiàn)了不一一解決之,最終會(huì)導(dǎo)致不斷的繁衍,終有一日,屋里的主人,會(huì)被細(xì)菌病毒侵襲。
碼文不易。希望讀到這的您能分享和關(guān)注一下我,以后還會(huì)分享Android知識(shí)點(diǎn)及解析,您的支持就是我最大的動(dòng)力!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。