起因
最近在维护公司一老项目,发现客户使用的包的版本号比git上高不少,这意味着该项目代码可能没有提交,顿时心中一凉,因为负责这个项目的同事已经离职,电脑也已经被回收,所以想找到这个项目文件是不可能了,那只能去尝试恢复这部分代码了,下面记录一下我的操作过程,以供参考。
过程
注意:下面的操作都在windows环境下进行,linux和mac用户自行替换相关命令,原理是一样的
1.准备apk文件
- 首先需要找到你要恢复的版本对应的apk文件,最好是未开启混淆的版本(比如debug包),不然很难操作
- 然后使用当前项目文件重新打包一个和上述版本一致的包(打包参数一致,比如都是debug包,相同渠道,目的是排除不必要的差异)
2.提取jar文件
将apk中的dex文件转为jar文件,这一步需要借助dex2jar这个工具,使用也是非常简单
d2j-dex2jar.cmd .\xxx.apk
之后会在当前目录生成一个jar文件(支持multiple dex)
两个apk都要提取
3.从jar文件中提取出自己项目包名下的代码
jar文件可以直接用解压软件打开,找到自己包名下的代码后直接拖出来即可,这一步的目的是排除依赖的三方代码的影响,只关注自己的项目代码。
提取后的代码文件夹,可以使用jar命令打包成jar文件,首先进入到要打包的文件夹根目录,执行下面命令
jar.exe cvf xxx.jar *
4.比对jar文件差异
通过上面的步骤操作,我们已经得到了两个只包含我们自己项目代码的jar文件,接下来需要使用jarcomp这个工具比对下代码差异,这个工具是一个jar文件,使用方法如下,a.jar b.jar是需要比对的jar文件
java -jar jarcomp.jar a.jar b.jar
执行后你会得到一个如下图所示的弹框
黄色部分是两个文件之间的差异,有了这个差异性列表之后,我们就可以去替换代码了
5.代码替换
首先需要打开你要恢复的这个版本的jar文件,这一步我们使用jadx,下载后,找到jadx-gui.bat这个文件,运行它,之后你需要配置下,将调试信息关掉,否则代码中将会有调试信息的注释
方法如下:文件->首选项
打开jar文件后,你就可以按照步骤4中拿到的差异性列表来找到对应的文件,然后将内容替换到你的项目中,这是一个非常考验耐心和细心的活,慢慢来
这里需要说明下,由于代码是反编译的,所以代码中的常量都是直接显示的,比如
-
setVisibility(View.GONE)反编译后就是setVisibility(8)
-
getSystemService(Context.AUDIO_SERVICE)反编译后就是getSystemService("audio")
等等 不影响运行,但是这样肯定没法维护,所以要自己替换回来
经过上面的操作后,代码部分基本就替换完成了,剩下的就是资源部分,改天抽空再写下吧。。