@wangwangheng
2015-05-27T10:58:05.000000Z
字数 7091
阅读 2979
公司文档
Proguard
是一款免费的Java类文件压缩器、优化器和混淆器。它能发现并删除无用类、字段(field)、方法和属性值(attribute)。它也能优化字节码并删除无用的指令。最后,它使用简单无意义的名字来重命名你的类名、字段名和方法名。经过以上操作的jar文件会变得更小,并很难进行逆向工程
Proguard工具通过移除不用的代码,用语义上混淆的名字来重命名类、字段和方法等手段来压缩、优化和混淆你的代码。结果是更小的.apk文件,并且更难于被反编译。由于ProGuard能够让你的程序难于被反编译,因此,当你的程序使用了一些机密的信息的时,使用它就显得更加重要。
Proguard已经集成到Android的编译环境中,因此,用不着手动来触发它。ProGuard只在release模式下编译应用程序才会运行,所以,在debug模式下编译,你就不必处理混淆的代码。是否运行ProGuard是完全可选的,但强烈推荐使用。
Java 源代码(.java文件)通常被编译为字节码(.class文件)。而完整的程序或程序库通常被压缩和发布成Java文档(.jar文件)。字节码比 Java源文件更简洁,但是它仍然包含大量的无用代码,尤其它是一个程序库的时候。ProGuard的压缩程序操作能分析字节码,并删除无用的类、字段和方法。程序只保留功能上的等价,包括异常堆栈描述所需要的信息
通常情况下,编译后的字节码仍然包含了大量的调试信息:源文件名,行号,字段名,方法名,参数名,变量名等等。这些信息使得它很容易被反编译和通过逆向工程获得完整的程序。有时,这是令人厌恶的。例如像ProGuard这样的混淆器就能删除这些调试信息,并用无意义的字符序列来替换所有名字,使得它很难进行逆向工程,它进一步免费的精简代码。除了异常堆栈信息所需要的类名,方法名和行号外,程序只会保留功能上的等价。
除了在压缩操作删除的无用类,字段和方法外,ProGuard也能在字节码级提供性能优化,内部方法有:
实际的优化效果是依赖于你的代码和执行代码的虚拟机的。简单的虚拟机比有复杂JIT编译器的高级虚拟机更有效。无论如何,你的字节码会变得更小。
一些情况下,默认配置就足够了。然而,有些情况Proguard也很难正确分析,它可能会删除它认为不用的代码,但实际上正是你的程序所需要的。例如:
默认的配置文件文件努力去覆盖通用的情况,但有可能你会遇到如ClassNotFoundException
这样的异常,而这正好是由于Proguard移除了整个类造成的。
你可以修正由于ProGuard移除代码造成的错误,只需要在proguard.cfg文件中添加一行-keep
。例如:
-keep public class <MyClass>
使用-keep选项时,有一些选项和建议,因此,强烈建议你阅读Proguard手册来了解更多关于定制配置文件的信息。Overview of Keep options和“Examples section”将非常有用。而“Troubleshooting”章节也列出了一些当你的代码被删除时你可能会遇到的一些常见问题
当你在release模式下编译你的程序,不管是用ant release还是用Eclipse的导出向导,编译系统都会自动检查proguard.config属性是否设置。如果设置了,ProGuard就会在打包成.apk文件之前,自动处理应用程序的字节码。Debug模式编译,不会触发ProGuard,因为它会使得调试更加复杂累赘
引用网络资源并整理
取消project.properties里面关于proguard的注释。这一步可以开启proguard。根据网上的博客,最好加上sdk的路径。
sdk.dir=D:/Android/android_sdk
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
这样一来默认的配置文件也会被包括进来。
保存被AndroidManifest.xml调用或者webview的类。这是因为proguard会移除没有被调用的代码
-keepclassmembers class fqcn.of.javascript.interface.for.webview
{
public *;
}
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
第三方类库
-keep class android.** {*;}
-keep class com.jeremyfeinstein.slidingmenu.lib.** {*;}
-keep class com.actionbarsherlock.** {*;}
-keep class com.lidroid.xutils.** {*;}
其实这一步可以代替上面所有的keep语句,彻底将误删的概率降到最低。
那就是保留所有具有公有访问权限的类和其公共成员。
-keepclasseswithmembers class *{
public *;
}
在github上的开源proguarddemo上学来的,删除Log代码
-assumenosideeffects class android.util.Log {
public static *** e(...);
public static *** w(...);
public static *** wtf(...);
public static *** d(...);
public static *** v(...);
}
在混淆完成之后会生成一些文件,这些文件放在以下文件夹中:
注意:每当你在release模式下编译时,这些文件都会被覆盖重写,当然,是被Proguard工具生成的最新的文件所覆盖。每次你发布你的程序时,都应该保存一份,为了将来能够解码bug报告。
描述.apk文件中所有类文件间的内部结构
列出了原始的类,方法和字段名与混淆后代码间的映射。这个文件很重要,当你从release版本中收到一个bug报告时,可以用它来翻译被混淆的代码。
retrace.bat
脚本(Window)或retrace.sh
脚本(Linux,Mac OS X)可以将一个被混淆过的堆栈跟踪信息还原成一个可读的信息。它位于<sdk_root>/tools/proguard
文件夹中。执行retrace工具的语法如下:
retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]
例如:
retrace.bat -verbose mapping.txt obfuscated_trace.txt
如果你没有指定,retrace工具会从标准输入读取。
每次发布程序给用户时,都应该保存一份mapping.txt。这样的话,当用户遇到一个bug并提交一个混淆的堆栈信息,能确保你能调试这个问题。工程的mapping.txt文件在你每次进行release编译时都会被覆盖,所以,你一定要小心的保存你需要的版本。
列出了未被混淆的类和成员
列出了从.apk中删除的代码
最新的配置,最好去相关的开源项目或者第三方SDK去查找
1、Gson混淆
-keepattributes Signature
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.examples.android.model.** { *; }
2、greenDao混淆
-libraryjars libs/greendao-1.3.7.jar
-keep class de.greenrobot.dao.** {*;}
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
3、volley混淆
-keep class com.android.volley.** {*;}
-keep class com.android.volley.toolbox.** {*;}
-keep class com.android.volley.Response$* { *; }
-keep class com.android.volley.Request$* { *; }
-keep class com.android.volley.RequestQueue$* { *; }
-keep class com.android.volley.toolbox.HurlStack$* { *; }
-keep class com.android.volley.toolbox.ImageLoader$* { *; }
4、sharesdk混淆
-keep class cn.sharesdk.**{*;}
-keep class com.sina.**{*;}
-keep class **.R$* {*;}
-keep class **.R{*;}
-dontwarn cn.sharesdk.**
-dontwarn **.R$*
5、UIL混淆
-keep class com.nostra13.universalimageloader.** { *; }
-keepclassmembers class com.nostra13.universalimageloader.** {*;}
6、高德地图sdk混淆
-libraryjars libs/android-support-v4.jar
-dontwarn android.support.v4.**
-keep class android.support.v4.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment
-libraryjars libs/MapApiLocation.jar
-libraryjars libs/MapApiSearch.jar
-libraryjars libs/Android_Map_V2.0.4.jar
-dontwarn com.amap.api.**
-dontwarn com.a.a.**
-dontwarn com.autonavi.**
-keep class com.amap.api.** {*;}
-keep class com.autonavi.** {*;}
-keep class com.a.a.** {*;}
7、unity混淆(需要修改proguard.jar文件)
-libraryjars f:/work_hb_v021/Lib_SocShare_v237_0804/libs/untiy-classes.jar
-dontwarn com.unity3d.player.**
-dontwarn org.fmod.**
-keep class com.unity3d.player.**{*;}
-keep class org.fmod.**{*;}
-keep public class * extends com.unity3d.player.**
-keep public class * extends org.fmod.**
注:还需要对与unity交互的相关方法或者类(jni)进行混淆配置。
8、内部类或者内部接口类的混淆配置
-keep class com.manjay.housebox.activity.CityListActivity$*{
<fields>;
<methods>;
}
-keepclassmembers class com.manjay.housebox.activity.CityListActivity$*{*;}
-keep class com.manjay.housebox.map.MapActivity$*{
<fields>;
<methods>;
}
-keepclassmembers class com.manjay.housebox.map.MapActivity$*{*;}
9、pinyin4j
-dontwarn net.soureceforge.pinyin4j.**
-dontwarn demo.**
-libraryjars libs/pinyin4j-2.5.0.jar
-keep class net.sourceforge.pinyin4j.** { *;}
-keep class demo.** { *;}
10、volley
-libraryjars libs/volley.jar
11、async http
-libraryjars libs/android-async-http-1.4.5.jar
12、JPush
-libraryjars libs/jpush-sdk-release1.6.3.jar
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
13、EventBus
-libraryjars libs/eventbus-1.0.1.jar
-keepclassmembers class ** {
public void onEvent*(**);
}
-keepclassmembers class ** {
public void xxxxxx(**); //所有监听的方法都要列在这里
}
14、SlidingMenu
-dontwarn com.jeremyfeinstein.slidingmenu.lib.**
-keep class com.jeremyfeinstein.slidingmenu.lib.**{*;}
15、ActionBarSherlock
-dontwarn com.actionbarsherlock.**
-keep class com.actionbarsherlock.**{*;}
17、asmack-android-19-0.8.10.jar 聊天xmpp 第三方jar
-libraryjars libs/asmack-android-19-0.8.10.jar
-keep class com.kenai.jbosh.** {*; }
-keep class com.novell.sasl.client.** {*; }
-keep class de.measite.smack.** {*; }
-keep class org.** {*; }
/**如果项目用到jar的接口 此方不加,会有问题**/
-keep interface com.kenai.jbosh.** {*; }
-keep interface com.novell.sasl.client.** {*; }
-keep interface de.measite.smack.** {*; }
-keep interface org.** {*; }