Apk/Jar包混淆方法
1.可视化工具
Android sdk中提供了混淆代码的工具路径在..\android-sdk\tools\proguard下,运行android-sdk\tools\proguard\bin\proguardgui.bat可以进行可视化混淆,这里混淆有两种方式:1.直接load已经配置好的proguard.cfg文件,即可混淆
2.按照提示向导添加proguard配置信息
2.Eclipse中导出混淆apk/jar
Eclipse中New Android Project,选择Create new project in workspace 时,会自动产生基本的混淆配置文件proguard.cfg在工程目录下。(用已有代码创建新工程时,不会产生该文件,如果没有可以自己拷贝一个放置在工程根目录下。)
然后再在project.properties文件中加入proguard.config=proguard.cfg,则在生成apk/jar包时进行混淆。
3.混淆规则
混淆的原理不做描述。
默认情况下,proguard会混淆所有代码,但对于应用程序来说,例如带有so库的apk程序,有些代码是不能混淆的,否则就会出错。因此在编写混淆的proguard.cfg文件是,要特别注意,总结了一些规则,可参考:
一. 用到反射地方不能混淆
二. 代码依赖于系统的接口,比如被系统代码调用的回调方法
三. ava 元素名称是在配置文件中配置好的
四. Native方法
五. 被so库回调的方法
常见的不能混淆的androidCode
Android 程序,下面这样代码混淆的时候要注意保留。
Android系统组件,系统组件有固定的方法被系统调用。
被Android Resource 文件引用到的。名字已经固定,也不能混淆,比如自定义的View 。
Android Parcelable ,需要使用android 序列化的。
其他Anroid 官方建议不混淆的,如
android.app.backup.BackupAgentHelper
android.preference.Preference
com.android.vending.licensing.ILicensingService
Java序列化方法,系统序列化需要固定的方法。
枚举,系统需要处理枚举的固定方法。
本地方法,不能修改本地方法名
annotations 注释
数据库驱动
有些resource 文件
用到反射的地方
为了防止混淆出问题,你需要熟悉你所有的code ,系统的架构,以及系统和你code的集成的接口,并细心分析。同时你必须需要一轮全面的测试。所以混淆也还是有一定风险的。为了避免风险,你可以只是混淆部分关键的代码,但是这样你的也会有所降低。
4.proguard
常用配置选项
-dontwarn 缺省proguard 会检查每一个引用是否正确,但是第三方库里面往往有些不会用到的类,没有正确引用。如果不配置的话,系统就会报错。
-keep 指定的类和类成员被保留作为入口。
-keepclassmembers 指定的类成员被保留。
-keepclasseswithmembers 指定的类和类成员被保留,假如指定的类成员存在的话。
proguard 参数
-include {filename} 从给定的文件中读取配置参数
-basedirectory {directoryname} 指定基础目录为以后相对的档案名称
-injars {class_path} 指定要处理的应用程序jar,war,ear和目录
-outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称
-libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件
-dontskipnonpubliclibraryclasses 指定不去忽略非公共的库类。
-dontskipnonpubliclibraryclassmembers 指定不去忽略包可见的库类的成员。
保留选项
-keep {Modifier} {class_specification} 保护指定的类文件和类的成员
-keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好
-keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。
-keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)
-keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除)
-keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)
-printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件
压缩
-dontshrink 不压缩输入的类文件
-printusage {filename}
-whyareyoukeeping {class_specification}
优化
-dontoptimize 不优化输入的类文件
-assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用
-allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员
混淆
-dontobfuscate 不混淆输入的类文件
-printmapping {filename}
-applymapping {filename} 重用映射增加混淆
-obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称
-overloadaggressively 混淆时应用侵入式重载
-useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆
-flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中
-repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中
-dontusemixedcaseclassnames 混淆时不会产生形形色色的类名
-keepattributes {attribute_name,...} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.
-renamesourcefileattribute {string} 设置源文件中给定的字符串常量