瞬间感觉自己很niubility,有没有?
有时候,我们也经常用它来分析自己的Apk,例如,生成的安装包到底长什么样子,里面的资源/代码构成,Manifest
中配置是否如预期,又或者方法数,等等。但是,一次突然的机会,发现自己开发的Ap分析不了,一直处于Parsing Manifest
状态。
一脸懵逼,有木有?
二、探因
这个问题曾经困惑了我不少时间,之前也没有具体去研究过。现在又遇到了。瞬间想到鲁迅说的一句话:
技术路上,会遇到很多看似莫名其妙的问题,细心探究,解决了,就是成长。
无视它并避让过去,看似绕过了问题,实际上失去了一次很好的技术历练的机会,
并且下次很可能还会遇到类似的,甚至一样的问题,长期看将是困难和停滞。
既然先辈都这样说了,那就,那硬着头皮解一下?
2.1 AS日志
现在给人的感觉是Analyze APK
执行过程中直接停住了,后者长时间一直在分析。但不管怎样,毕竟是在AS中的操作,先查一下对应的AS日志,看看有没Parsing Manifest
或相关的日志信息,可以起到帮助的。
Help >> Show Log in Finder
,打开日志,对应时间点看了又看,没找到Parsing Manifest
直接相关的,不过,找到了控件显示先关的日志:
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中对应的Analyze Apk
相关的类名有ApkEditor
、ApkViewPanel
,包名是com.android.tools.idea.apk.viewer
。AS日志部分的有效信息只有这么多了。
2.2 系统全局搜索
AS日志中没有,那有没有可能存在有效的信息输出在了系统其它的地方?于是,直接花点时间,系统全局搜索下。
/ grep -rnl “Parsing Manifest” *
输出信息中有一些警告信息之类的,最终在输出信息中找到了个相关的:
Applications/Android Studio.app/Contents/plugins/android/lib/android.jar
看目录名,大概是AS插件中对应的Android相关的lib工具包。找到对应位置,用JD-GUI打开对应的jar文件,具体看下一下。
通过全局搜索关键字Parsing Manifest
,的确可以定位到具体的ApkViewPanel
类,且包名与上面AS日志中都能对的上,但字节码反解成java过程中有内部错误。尝试着用用jadx打开,因为android.jar包还挺大,时间比较长,、最终虽然ApkViewPanel
部分内容可以显示,但内部依然有部分内部错误无法显示,且Parsing Manifest
不能直接显示。
2.3 GitHub定位与源码分析
不过没关系,我们试着去找找源码看看。搜索对应包名:com.android.tools.idea.apk.viewer
,选择java类别,很快,我们找到了对应的源码位置。
正好,AS就是JetBrains主导的产品,Perfect!
很快,我们找到了对应Parsing Manifest
的位置:
setAppInfo()
方法中,将对应的控件内容从原来的Parsing Manifest
改成了对应的包名和版本号等信息。
显然,在代码myNameComponent.append("Parsing Manifest");
与setAppInfo(result);
之间,程序出了问题。
这之间关键的类,主要有apkParser
对象对应的ApkParser
类,还有Archives
类。继续跟踪ApkParser
类,发现其主要也是一个外壳性质的类,apkParser.constructTreeStructure()
方法主要流程来到如下所示位置:
现在,我们发现,无论是此处的ArchiveTreeStructure
类,还是之前的Archives
类,这两个关键线索上的类都不是在这个项目中。根据代码文件中的import
导入,很快,我们发现,线索被定向到了com.android.tools.apk.analyzer
包中。
从包名上来看,com.android.tools.apk.analyzer
应该是Android Tools
中带的一个工具。来到项目iml
文件,我们发现与之相关的构件。其中,组名是:com.android.tools.apkparser
,构件名是:apkanalyzer
。
2.4 工具本体-apkanalyzer
至此,我们先总结下问题的原因。
AS中自带的Analyze APK,实际上是通过集成了插件实现,而插件内部,又通过调用了 Android Tools中的名叫apkanalyzer
的工具实现的分析。因此,想要追溯出现问题的原因,我们需要再去对应追踪下apkanalyzer
。
如果熟悉Android Tools,我们对应去tools目录下找找,很快便能找到apkanalyzer
。及时不熟悉,不知道目录位置也没关系,打不了全局搜索下。
终于,对应的工具本体出现在我们面前。
实际上,如果对Google Developer比较熟悉,或者直接在上面搜索下,也能直接在Analyze APK
页面上找到核心信息,直接指向工具本体—apkanalyzer
。
developer.android.com/studio/buil…
啊哈,饶了半天,原来官方文档上直接有啊,哭了,有木有?
同样的,通过反编译工具查看apkanalyzer.jar
代码终究不太方便,且内部也有不少INNER ERROR
。于是,我们继续去GitHub上找找。
GitHub上搜索到的apkanalyzer
相关的零零散散,好像都是个人的,不太官方,也不符合我们的预期。怎么办呢?
源码不够,Google Source来凑!
直接Google Source搜索可能的关键字,马上得到了结果。
显然,这正是我们需要的。
但此时,如果直接源码跟踪下去,还是有难度的。
2.5 apkanalyzer查因
apkanalyzer
作为一个工具,是独立的。在实际使用时可以直接脱离AS环境,Google Developer官网上也有专门的篇幅进行了介绍。
developer.android.com/studio/comm…
实际使用时,我们通过不同的命令行命令及参数,可以得到我们期望的结果,如用来分析APK基本属性,Manifest,dex或资源等。
由此,我们可以多试几个,反正AS中Analyze APK
最终用的也是它。在一定的命令上,结果肯定是一样的。也就是说,通过命令行直接执行apkanalyzer
,肯定也会有问题,但有个好处时,命令行执行往往都能抛出对应的错误日志。
有了进一步的错误日志提示,就有了异常栈和关键性的真正的错误原因信息。
那我们就试一试吧。
➜ 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.apk
classes7.dex
classes6.dex
classes5.dex
classes4.dex
classes3.dex
classes2.dex
classes.dex
复制代码
➜ 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.(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内所有文件列表的时候出现了问题。并且有对应的调用栈信息抛出。
从调用栈中我们发现,命令行的调用方式,是通过ApkAnalyzerCli
中的main
方法去接收命令参数的。在ApkAnalyzer.jar
同级的目录中,我们发现了有对应的ApkAnalyzerCli.jar
,其作用,就是基于ApkAnalyzer.jar
基础上封装的一个Client
,以方便程序被外部调用执行,如通过命令行的方式等。
并且,突然间发现,此处的栈信息与之前GitHub上JetBrains/android项目中分析到的源码位置相同~!!
at com.android.tools.apk.analyzer.ArchiveTreeStructure.create(ArchiveTreeStructure.java:100)
看来,这就是真实的原因所在了。
2.6 项目查因
设计模式学习笔记
设计模式系列学习视频
参考docs.qq.com/doc/DSkNLaERkbnFoS0ZF
目录中,我们发现了有对应的ApkAnalyzerCli.jar
,其作用,就是基于ApkAnalyzer.jar
基础上封装的一个Client
,以方便程序被外部调用执行,如通过命令行的方式等。
并且,突然间发现,此处的栈信息与之前GitHub上JetBrains/android项目中分析到的源码位置相同~!!
at com.android.tools.apk.analyzer.ArchiveTreeStructure.create(ArchiveTreeStructure.java:100)
看来,这就是真实的原因所在了。
2.6 项目查因
设计模式学习笔记
[外链图片转存中…(img-ZBDWKhuY-1724262737027)]
设计模式系列学习视频
[外链图片转存中…(img-5Rrj9GP6-1724262737027)]
参考docs.qq.com/doc/DSkNLaERkbnFoS0ZF