AndroidStudio对包含已混淆的第三方jar包的项目进行代码

关于项目的代码混淆这块,困扰了我一周之久,今天终于把问题解决了,在这里跟大家分享一下解决的过程,如果有和我情况相同的可以借鉴一下。

话说关于proguard进行代码混淆我也是第一次,从网上查看了一些教程就开始尝试了。使用的是Android SDK中自带的proguard,放在sdk\tools\proguard目录中。
首先遇到的问题就是,网络上大部分的教程都是使用eclipse时的操作方法,说明的很详细,在这里列举一篇文章供大家参考:http://blog.csdn.net/hudashi/article/details/9016805。然而我现在使用的是AndroidStudio的话显然这种方式并不适用了。

研究一下发现AndroidStudio是借助gradle来帮助配置混淆打包的,使用方法也很简单,在项目的build.gradle配置文件中加入如下代码即可:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
}
这里有两个需要注意的问题:
一是AndroidStudio生成的项目中有两个build.gradle配置文件,上面使用的是app目录中的那个。在生成项目的时候其实已经有默认的代码的,只需稍加修改即可。
二是由于gradle的版本不同,上面的代码可能有些改动:在gradle2.2之前的版本,使用的是runProguard true,而在gradle2.2之后的版本则使用的是minifyEnabled true。而查看项目使用的gradle的版本方法:File——>Setting,搜索中输入gradle,再Gradle Home中说明。


下面再来说明一下配置文件中说明的两个配置文件:proguard-android.txt和proguard-project.txt。这两个文件在我的proguard目录中已经存在了,我看有的文章中说新版的proguard文件目录中是没有这些文件需要自己补充的。如果你的目录中没有的话那就自己复制一份好了。
proguard-android.txt这个文件只需要放在proguard目录中就好了,项目打包的时候会根据使用的sdk的路径直接找到这个文件并读取配置的。而proguard-project.txt这个文件,根据文件名称也是要放在项目目录中的,位置就在build.gradle配置文件的同级目录中,也就是app/下。
(再说一下这两个文件的作用,当然都可以配置混淆打包的一些规则,在我多次尝试后发现这两个配置文件中的规则都是生效的,所以规则放在哪个文件中都可以,个人建议把项目相关的规则放在project这个中,Android这个中放一些公共的规则,我猜想这也许就是这样设计的目的吧。当然我也是刚刚学的这个,也许上面的理解并不准确哈!至于文件中的规则网上说明的有很多,我就不说了。这里给大家一个参考:http://blog.sina.com.cn/s/blog_4e1e357d0101cjz8.html。)

说了这么多终于要开始打包啦,方法跟没有混淆的时候就没有区别了。直接build->Generated signed APK就好了,在我以为已经没有问题的时候问题来了。出现了一个困扰了我好多天的错误,如下:
Error:Execution failed for task ':app:proguardRelease'.
> java.io.IOException: Can't read [E:\ide\XXX\app\libs\libammsdk.jar(; ; ; ; ; ; !META-INF/MANIFEST.MF)] (Can't process class [com/tencent/wxop/stat/al.class] (Unknown verification type [95] in stack map frame))

这个就比较让我无语了,微信分享当时就让我纠结了好久,结果没想到这个时候微信的包还给我找了麻烦。看了一下发现这个包已经做过一次代码混淆了。不知道怎么办的我上网搜索了下,嘿,还真有人遇到同样的问题并提供了解决办法。原文见这里:http://vase.iteye.com/blog/2171056。
热心的朋友们提供了解决方法,我就直接拿来尝试了。下载了重新编译的proguard,可以打开看了一下,确实已经将ClassConstants.java中StackMapTable属性改为dummy。于是直接拿这个proguard文件替换了原来的SDK中的文件夹。然后rebuild project后重新打包,没想到,还是原来的错误,一点都没有变化。我开始以为是项目的缓存,甚至重新打开AndroidStudio尝试,当然结果都很让人失望!

此后的两天里我一直各种尝试,然而这个错误一直跟着我,直到昨天我才发现了问题所在。废话不多说,直接上图:

这个是打包时候的进程中使用的的proguard位置,无语的发现人家并没有用SDK中的progard.jar,而是用了gradle自己的,位置在:C:\Users\用户\.gradle\caches\modules-2\files-2.1\net.sf.proguard\proguard-base\4.11\76730af417bb42da22b16e49f49e67863382b9bd\。当然我怎么替换问题都还在了。一直以来我没想到这点是因为很肯定它用的SDK中的proguard的配置文件,谁知道却没有就地取材用它的jar包。我也就很直接的将proguard/libs中的progard.jar直接替换了上图位置中的jar包,当然为了安全起见名字也换成了同样的。

OK,一下子就过去了,给大家看看我打包好了的结构:

说的有点啰嗦了,虽然不知道为什么AndroidStudio会使用这样的机制,好歹的我的混淆的包是出来了。安装尝试了下,微信分享的功能还是可以用的,并没有大家说的不能分享,这下我就放心了。

上述是我自己研究混淆打包的过程,有些地方可能理解的不到位,拿出来跟大家探讨一下。

    推荐阅读