Android-APK反编译可以获得XML布局文件吗

Android-APK反编译可以获得XML布局文件吗,第1张

1下载反编译工具

需要下载四个工具:dex2jar、JD-GUI、apktool、apktool-install-windows-r05-ibot

dex2jar:将apk中的classesdex转化成Jar文件

JD-GUI:反编译工具,可以直接查看Jar包的源代码。

apktool:反编译工具,通过反编译APK中XML文件,直接可以查看。

apktool-install-windows-r05-ibot:辅助windows批处理工具。

2解压缩APK包

apk文件也是一种常见的zip,常用的压缩软件就可轻松地解压apk文件。用压缩软件将apk文件中的文件解压到一个文件夹中,得到APK中的资源包括XML文件和classesdex文件,classesdex就是java文件编译再通过dx工具打包而成的。

解压截图:

3反编译dex文件

解压apk文件后,你会发现res目录的没有加密,但java源码编译成了一个classesdex文件,无法用普通的反编译class文件的方法来处理,dex2jar可以将dex文件转换成普通的jar包。

解压下载的dex2jar,把解压后的文件夹放到系统盘跟目录中并把这个目录加到系统path变量中,就可以直接用:dex2jarbat或dex2jarsh转换dex文件了。

DOS行命令如下:dex2jarbat xx\classesdex(xx是classesdex文件所在的路径)。

将在同目录得到普通jar包:classes_dex2jarjar,就可以用处理普通jar包的方法来反编译这个jar包得到原文件。

编译截图:

生成jar文件的截图如下:

4反编译jar包

得到jar包后,下载自已喜欢的反编译工具,推荐使用JD-GUI,有比较简单的图形界面,可以反编译单个class文件,也可以反编译jar包,比较方便。

打开压缩文件JD-GUI,运行jd-guiexe,打开上面生成的jar包,即可看到源代码了。

截图如下:

5反编译xml文件

打开解压的res\layout目录,有很多xml文件,如果你想看下作者是如何设计界面的,你会很失望,因为你看到的是一大堆乱码!这个时候我们需要用到的是apktool。

具体 *** 作方法:将下载的apktool和apktool-install-windows-r05-ibot两个包解压到同一个文件夹下,这个文件夹有三个文件:aaptexe,apktoolbat,apktooljar。把这个文件夹也放到系统盘的根目录中并把这个目录加到path变量中。以HelloWordapk为例:

在DOS命令行中输入:apktool d xx\HelloWordapk HelloWord得到HelloWord文件夹,此文件夹中的xml文件就是编译好的可以正常查看的文件。

截图如下:

生成的文件:

这样就得到了可以得到编译的源码和XML资源。

注意:文件的路径中最好不要出现中文!

我们知道,在 Android 中,View 绘制主要包含 3 大流程:

Android 中,主要有两种视图: View 和 ViewGroup ,其中:

虽然 ViewGroup 继承于 View ,但是在 View 绘制三大流程中,某些流程需要区分 View 和 ViewGroup ,它们之间的 *** 作并不完全相同,比如:

对 View 进行测量,主要包含两个步骤:

对于第一个步骤,即求取 View 的 MeasureSpec ,首先我们来看下 MeasureSpec 的源码定义:

MeasureSpec 是 View 的一个公有静态内部类,它是一个 32 位的 int 值,高 2 位表示 SpecMode(测量模式),低 30 位表示 SpecSize(测量尺寸/测量大小)。

MeasureSpec 将两个数据打包到一个 int 值上,可以减少对象内存分配,并且其提供了相应的工具方法可以很方便地让我们从一个 int 值中抽取出 View 的 SpecMode 和 SpecSize。

一个 MeasureSpec 表达的是:该 View 在该种测量模式(SpecMode)下对应的测量尺寸(SpecSize)。其中,SpecMode 有三种类型:

对 View 进行测量,最关键的一步就是计算得到 View 的 MeasureSpec ,子View 在创建时,可以指定不同的 LayoutParams (布局参数), LayoutParams 的源码主要内容如下所示:

其中:

LayoutParams 会受到父容器的 MeasureSpec 的影响,测量过程会依据两者之间的相互约束最终生成子View 的 MeasureSpec ,完成 View 的测量规格。

简而言之,View 的 MeasureSpec 受自身的 LayoutParams 和父容器的 MeasureSpec 共同决定( DecorView 的 MeasureSpec 是由自身的 LayoutParams 和屏幕尺寸共同决定,参考后文)。也因此,如果要求取子View 的 MeasureSpec ,那么首先就需要知道父容器的 MeasureSpec ,层层逆推而上,即最终就是需要知道顶层View(即 DecorView )的 MeasureSpec ,这样才能一层层传递下来,这整个过程需要结合 Activity 的启动过程进行分析。

我们知道,在 Android 中, Activity 是作为视图组件存在,主要就是在手机上显示视图界面,可以供用户 *** 作, Activity 就是 Andorid 中与用户直接交互最多的系统组件。

Activity 的基本视图层次结构如下所示:

Activity 中,实际承载视图的组件是 Window (更具体来说为 PhoneWindow ),顶层View 是 DecorView ,它是一个 FrameLayout , DecorView 内部是一个 LinearLayout ,该 LinearLayout 由两部分组成(不同 Android 版本或主题稍有差异): TitleView 和 ContentView ,其中, TitleView 就是标题栏,也就是我们常说的 TitleBar 或 ActionBar , ContentView 就是内容栏,它也是一个 FrameLayout ,主要用于承载我们的自定义根布局,即当我们调用 setContentView() 时,其实就是把我们自定义的布局设置到该 ContentView 中。

当 Activity 启动完成后,最终就会渲染出上述层次结构的视图。

因此,如果我们要求取得到子View 的 MeasureSpec ,那么第一步就是求取得到顶层View(即 DecorView )的 MeasureSpec 。大致过程如下所示:

经过上述步骤求取得到 View 的 MeasureSpec 后,接下来就可以真正对 View 进行测量,求取 View 的最终测量宽/高:

Android 内部对视图进行测量的过程是由 View#measure(int, int) 方法负责的,但是对于 View 和 ViewGroup ,其具体测量过程有所差异。

因此,对于测量过程,我们分别对 View 和 ViewGroup 进行分析:

综上,无论是对 View 的测量还是 ViewGroup 的测量,都是由 View#measure(int widthMeasureSpec, int heightMeasureSpec) 方法负责,然后真正执行 View 测量的是 View 的 onMeasure(int widthMeasureSpec, int heightMeasureSpec) 方法。

具体来说, View 直接在 onMeasure() 中测量并设置自己的最终测量宽/高。在默认测量情况下, View 的测量宽/高由其父容器的 MeasureSpec 和自身的 LayoutParams 共同决定,当 View 自身的测量模式为 LayoutParamsUNSPECIFIED 时,其测量宽/高为 android:minWidth / android:minHeight 和其背景宽/高之间的较大值,其余情况皆为自身 MeasureSpec 指定的测量尺寸。

而对于 ViewGroup 来说,由于布局特性的丰富性,只能自己手动覆写 onMeasure() 方法,实现自定义测量过程,但是总的思想都是先测量 子View 大小,最终才能确定自己的测量大小。

当确定了 View 的测量大小后,接下来就可以来确定 View 的布局位置了,也即将 View 放置到屏幕具体哪个位置。

View 的布局过程由 View#layout() 负责,其源码如下:

View#layout() 主要就做了两件事:

ViewGroup 的布局流程由 ViewGroup#layout() 负责,其源码如下:

可以看到, ViewGroup#layout() 最终也是通过 View#layout() 完成自身的布局过程,一个注意的点是, ViewGroup#layout() 是一个 final 方法,因此子类无法覆写该方法,主要是 ViewGroup#layout() 方法内部对子视图动画效果进行了相关设置。

由于 ViewGroup#layout() 内部最终调用的还是 View#layout() ,因此, ViewGroup#onLayout() 就会得到回调,用于处理 子View 的布局放置,其源码如下:

由于不同的 ViewGroup ,其布局特性不同,因此 ViewGroup#onLayout() 是一个抽象方法,交由 ViewGroup 子类依据自己的布局特性,摆放其 子View 的位置。

当 View 的测量大小,布局位置都确定后,就可以最终将该 View 绘制到屏幕上了。

View 的绘制过程由 View#draw() 方法负责,其源码如下:

其实注释已经写的很清楚了, View#draw() 主要做了以下 6 件事:

我们知道,在 Activity 启动过程中,会调用到 ActivityThreadhandleResumeActivity() ,该方法就是 View 视图绘制的起始之处:

可以看到, ActivityThreadhandleResumeActivity() 主要就是获取到当前 Activity 绑定的 ViewManager ,最后调用 ViewManageraddView() 方法将 DecorView 设置到 PhoneWindow 上,也即设置到当前 Activity 上。 ViewManager 是一个接口, WindowManager 继承 ViewManager ,而 WindowManagerImpl 实现了接口 WindowManager ,此处的 ViewManageraddView() 实际上调用的是 WindowManagerImpladdView() ,源码如下所示:

WindowManagerImpladdView() 内部转发到 WindowManagerGlobaladdView() :

在 WindowManagerGlobaladdView() 内部,会创建一个 ViewRootImpl 实例,然后调用 ViewRootImplsetView() 将 ViewRootImpl 与 DecorView 关联到一起:

ViewRootImplsetView() 内部首先关联了传递过来的 DecorView (通过属性 mView 指向 DecorView 即可建立关联),然后最终调用 requestLayout() ,而 requestLayout() 内部又会调用方法 scheduleTraversals() :

ViewRootImplscheduleTraversals() 内部主要做了两件事:

ChoreographerpostCallback() 会申请一次 VSYNC 中断信号,当 VSYNC 信号到达时,便会回调 ChoreographerdoFrame() 方法,内部会触发已经添加的回调任务, Choreographer 的回调任务有以下四种类型:

因此, ViewRootImplscheduleTraversals() 内部通过 mChoreographerpostCallback(ChoreographerCALLBACK_TRAVERSAL, mTraversalRunnable, null) 发送的异步视图渲染消息就会得到回调,即回调 mTra

以上就是关于Android-APK反编译可以获得XML布局文件吗全部的内容,包括:Android-APK反编译可以获得XML布局文件吗、Android - View 绘制流程、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/10642606.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-10
下一篇 2023-05-10

发表评论

登录后才能评论

评论列表(0条)

保存