ref:
ProGuard基础语法和打包配置.md
https://github.com/D-clock/Doc/blob/master/Android/Gradle/3_ProGuard%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%92%8C%E6%89%93%E5%8C%85%E9%85%8D%E7%BD%AE.md
AndroidStudio下ProGuard混淆打包
https://github.com/D-clock/Doc/blob/master/Android/Gradle/4_AndroidStudio%E4%B8%8BProGuard%E6%B7%B7%E6%B7%86%E6%89%93%E5%8C%85.md
proguard-rules.pro 模板
https://github.com/AnyLifeZLB/AndroidAppFrameWork/blob/master/main/proguard-rules.pro
Proguard官方使用手册:
https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#manual/usage.html
压缩代码和资源 | Android Studio
https://developer.android.com/studio/build/shrink-code.html?hl=zh-cn
Android打包的那些事 - 谦虚的天下 - 博客园
http://www.cnblogs.com/qianxudetianxia/p/4948499.html
ProGuard代码混淆技术详解 - cryAllen - 博客园
http://www.cnblogs.com/cr330326/p/5534915.html
Android Proguard(混淆) - 简书
http://www.jianshu.com/p/60e82aafcfd0
代码压缩通过 ProGuard 提供,ProGuard 会检测和移除封装应用中未使用的类、字段、方法和属性,包括自带代码库中的未使用项(这使其成为以变通方式解决 64k 引用限制的有用工具)。ProGuard 还可优化字节码,移除未使用的代码指令,以及用短名称混淆其余的类、字段和方法。混淆过的代码可令您的 APK 难以被逆向工程,这在应用使用许可验证等安全敏感性功能时特别有用。
要启用资源压缩,请在 build.gradle
文件中将 shrinkResources
属性设置为 true
(在用于代码压缩的 minifyEnabled
旁边)。例如:
android { ... buildTypes { release { shrinkResources true minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
如果您尚未使用代码压缩用途的 minifyEnabled
构建应用,请先尝试使用它,然后再启用 shrinkResources
,因为您可能需要编辑 proguard-rules.pro
文件以保留动态创建或调用的类或方法,然后再开始移除资源。
8. 混淆技巧
混淆能让反编译的代码可读性变的很差,而且还能显著的减少APK包的大小。
1). 第一个技巧
相信很多朋友对混淆都觉得麻烦,甚至说,非常乱。因为添加混淆规则需要查询官方说明文档,甚至有的官方文档还没说明。当你引用了太多库后,添加混淆规则将使一场噩梦。
这里介绍一个技巧,不用查官方文档,不用逐个库考虑添加规则。
首先,除了默认的混淆配置(android-sdk/tools/proguard/proguard-android.txt), 自己的代码肯定是要自己配置的:
## 位于module下的proguard-rules.pro
#####################################
######### 主程序不能混淆的代码 #########
#####################################
-dontwarn xxx.model.**
-keep class xxx.model.** { *; }
## 等等,自己的代码自己清楚
#####################################
########### 不优化泛型和反射 ##########
#####################################
-keepattributes Signature
接下来是麻烦的第三方库,一般来说,如果是极光推的话,它的包名是cn.jpush, 添加如下代码即可:
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
其他的第三库也是如此,一个一个添加,太累!其实可以用第三方反编译工具(比如jadx:https://github.com/skylot/jadx ),打开apk后,一眼就能看到引用的所有第三方库的包名,把所有不想混淆或者不确定能不能混淆的,直接都添加又有何不可:
#####################################
######### 第三方库或者jar包 ###########
#####################################
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-dontwarn com.squareup.**
-keep class com.squareup.** { *; }
-dontwarn com.octo.**
-keep class com.octo.** { *; }
-dontwarn de.**
-keep class de.** { *; }
-dontwarn javax.**
-keep class javax.** { *; }
-dontwarn org.**
-keep class org.** { *; }
-dontwarn u.aly.**
-keep class u.aly.** { *; }
-dontwarn uk.**
-keep class uk.** { *; }
-dontwarn com.baidu.**
-keep class com.baidu.** { *; }
-dontwarn com.facebook.**
-keep class com.facebook.** { *; }
-dontwarn com.google.**
-keep class com.google.** { *; }
## ... ...
2). 第二个技巧
一般release版本混淆之后,像友盟这样的统计系统如果有崩溃异常,会记录如下:
java.lang.NullPointerException: java.lang.NullPointerException
at com.xxx.TabMessageFragment$7.run(Unknown Source)
这个Unknown Source是很要命的,排除错误无法定位到具体行了,大大降低调试效率。
当然,友盟支持上传Mapping文件,可帮助定位,mapping文件的位置在:
project > module
> build > outputs > {flavor name} > {build type} > mapping.txt
如果版本一多,mapping.txt每次都要重新生成,还要上传,终归还是麻烦。
其实,在proguard-rules.pro中添加如下代码即可:
-keepattributes SourceFile,LineNumberTable
当然apk包会大那么一点点(我这里6M的包,大个200k吧),但是再也不用mapping.txt也能定位到行了,为了这种解脱,这个代价我个人觉得是值的,而且超值!