您的位置:首页 > 移动开发 > Android开发

精华Android中ProGuard的使用ZZ 分类: Android安装及配置 2014-05-30 10:55 139人阅读 评论(0) 收藏

2014-05-30 10:55 656 查看
http://www.apkbus.com/android-122624-1-1.html

由于最近做的一个项目集成了支付宝的sdk,debug模式下完全正常运行,发布release版本时无法正常支付,经过艰辛的debug才发现是代码混淆的原因。故而有了这篇教程,给像我一样的开发小白看看,高手轻喷。后面打算整个实例测试以下,今天先到这了,翻译翻的眼疼。(未完待续)

=================原创教程============================

1、什么是ProGuard 工具?

ProGuard 是 通过移除没用的代码、重命名相关类和方法等方式对代码进行优化、压缩、混淆的一个工具。

android中ProGuard已经被整合到开发工具中,官方强烈建议使用。对于调试模式,该工具不会被启用。

2、ProGuard 的使用

当你创建项目时,在项目的根目录下会自动生成proguard.cfg文件,该文件就是ProGuard的配置文件,使用方法也比较简单:在project.properties文件中添加"proguard.config=proguard.cfg"即可。默认生成的ProGuard文件只是用与一般的情况(仅仅覆盖了Android中几个比较重要的类)。所以大部分情况下我们需要自己定制该配置文件。

当然,上述情况是proguard.cfg文件位于项目的根目录下,如果你愿意你也可以挪动到别的地方,不过properties文件中需指明路径。

项目发布时会自动调用ProGuard工具混淆,从而在项目文件夹下面会生成

dump.txt: 描述.apk文件中所有类文件间的内部结构

mapping.txt:列出了原始的类,方法和字段名与混淆后代码间的映射。这个文件很重要,当你从release版本中收到一个bug报告时,可以用它来翻译被混淆的代码。

seeds.txt:列出了未被混淆的类和成员

usage.txt:列出了从.apk中删除的代码

这几个文件主要描述了整个混淆的过程包括名称替换部分的详细描述。由于混淆后的代码输出的调试信息有可能因为混淆也变得难以识别,这时你就需要借助这几个文件来查询原始信息了。

3、ProGuard的配置

一般情况下ProGuard会正常工作,但是别忘了它也有犯浑的时候。有时间他会把项目中实际有用的代码移除,然后向您报告ClassNotFoundException!!例如:

仅仅被AndroidManifest.xml文件引用的类

由JNI调用的方法

动态引用的属性和方法

如果某个类被错误地移除了,你可以这样修复:

proguard.cfg配置文件中添加 -keep public class 即可。

当然就代码安全性而言,SDK中还给出了以下的建议以保护敏感代码:

多使用方法嵌套调用

少使用字符串常量,尽量动态构造

使用反射进行方法调用

对于新版本的ADT默认已经不再生成 proguard.cfg文件,而是生成proguard-project.txt文件,因此我们有关ProGuard的配置写到这个文件即可,对于properties文件的配置,可以这么写:proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

相信大家都能看明白,${sdk.dir}/tools/proguard/proguard-android.txt文件引用的是默认配置(即所有项目通用的),proguard-project.txt是项目下面针对该项目的配置,最终配置由这两部分组成。

=======================我是分割线====================================

(以下内容摘自互联网)

===================================================================

-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, andInnerClasses.

-renamesourcefileattribute {string} 设置源文件中给定的字符串常量

===========================Theend===========================================

===============以下内容为对ProGuard官方文档的翻译及总结=================================

ProGuard的工作原理:



ProGuard 读取jars(包括wars, ears, zips, ordirectories)。input这一部分可以是源文件,源文件的类名称与混淆后类名称一一对应。

凡是正常编译所需的jar文件都需要添加到 Inputjars中。jar文件一般不会被处理,但是你仍需将它们添加到classpath中。

应用程序入口

为了识别项目中哪些类需要保留,那些需要被移除,你需要定义程序的入口,如main函数的类,activity等。

shrinking:这一步中,ProGuard会从入口处递归查询,那些没有被用到的类和方法将会被移除。

optimization :这一步中,ProGuard会进一步优化程序,非公开的类和方法将会有可能被 private, static,or final化,没有用的参数将会被移除,有一些函数将会被内联。

obfuscation:这一步中:对于非入口的类与方法,ProGuard将会对类和其中的方法属性进行重命名,

preverification :该步仅适用于入口程序无关紧要的项目。

对于动态加载的类或方法,最好也要将其作为入口点。

ProGuard的使用

java -jar proguard.jar options ...

或者将options写入到相应的配置文件中

java -jar proguard.jar @myconfig.pro

配置文件中使用“#”作为行注释。

多余的空格将会被忽略,如果文件名中含有空格那么需要使用单引号或者双引号。

配置可以任意分组,其数量是不被限制的。

配置不分先后顺序,为了方便检索,你可以按照首字母进行排序。

input/output相关命令

-include filename 包含其他的配置文件

-basedirectorydirectoryname 设置基准文件夹位置,所有的其他配置中的路径都是基于该文件夹。

-injars class_path 设置将要被处理的jar(or wars, ears, zips, ordirectories)文件。默认情况下所有非class文件将会被按原样拷贝。所以,请注意中间文件。

-outjars class_path 指定对应的输出文件,但是应避免将输出文件直接覆盖输入文件,如果不配置outjars将不会有输出。

注:input 与 output都可以设置过滤器,可指明多个。

-libraryjars class_path指明库文件位置这些jar文件不会被输出到output中。库文件中的类应是被继承而不仅仅是被使用的。需要注意的是ProGuard不会从基准文件夹或者ProGuard的运行文件夹中寻找库文件。

-skipnonpubliclibraryclasses跳过库文件中非公开类的处理,来加快ProGuard的处理速度。但是如果有公开的类继承了某非公开类,那么此条命令将会导致错误。

-dontskipnonpubliclibraryclasses 默认设置

-dontskipnonpubliclibraryclassmembers 声明不要跳过对非公开类中属性及方法的处理。默认情况下是跳过的,因为程序中不会引用它们,有些情况下人们编写的代码与类库中的类在同一个包下,并且对包中内容加以引用,此时需要加入此条声明。

-keepdirectories [directory_filter]声明output中需要保留的目录,默认情况下为减小jar文件的大小,目录都将被删除。可以添加过滤器,如果不加过滤器那么所有的目录都将被保留。

-target version 设置版本号,可以为1.0, 1.1, 1.2, 1.3, 1.4, 1.5 (or just 5),1.6 (or just 6), or 1.7 (or just 7).

-forceprocessing 强制处理。

Keep Options(保证不被移除)

-keep [,modifier,...] class_specification声明类和类中成员作为入口点保留。例如对于普通程序,需要声明Main类及其main函数,为了处理类库你需要将里面所有的公共域都声明为入口点。

-keepclassmembers [,modifier,...] class_specification如果类被保留那么类成员也将被保留,例如保留实现Serizable的类中所有的域。

-keepclasseswithmembers [,modifier,...] class_specification声明含有指定域的类都被保留,而不必一一列出,如保留所有含有main的类。

-keepnamesclass_specification 类似-keep,allowshrinking class_specification声明类成员的名称被保留,上一阶段(shriking)如果没有被移除的话。如需要保留所有实现Serizable的类得名称和域名称以实现与以前的代码兼容。

-keepclasseswithmembernames class_specification 是-keepclasseswithmembers,allowshrinking class_specification的简写,指定含有指定域的类或类中的域的名称被保留。例如保留本地方法及含有本地方法的类名。

-printseeds[filename] 列出所有被保留的类及其类中的域

Shrinking Options

-dontshrink 声明不压缩输入文件夹,默认情况下使用压缩的。

-printusage [filename] 列出被移除的代码。

-whyareyoukeeping class_specification 列出被移除的原因

Optimization Options

-dontoptimize 不优化。默认优化。

-optimizations optimization_filter专家级别的可选项,优化项过滤器。

-optimizationpasses n优化几轮,默认一轮,如果优化一轮后发现没有可优化的项目了,直接就停止了。

-assumenosideeffectsclass_specification 自定义没有作用的代码,Proguard会分析相关代码,如果这些代码确实没有其他作用将会被移除。例如移除loggingcode

-allowaccessmodification声明处理过程中,允许扩大访问修饰符。例如将get方法内联会将相关属性的访问修饰符设为public。如果设计为类库就应避免使用该设置项。

-mergeinterfacesaggressively声明接口可以被合并,尽管有些实现类并没有完全实现其中的方法。

ObfuscationOptions

-dontobfuscate 不使用混淆,默认使用混淆。类及其中的域都会被命名为一个更加简洁的名称。

-printmapping [filename] 将混淆前后对应的名称输出到指定的地点。

-applymapping filename 使用以前输出的混淆前后mapping。

-obfuscationdictionaryfilename 声明一个文本文件以提供可用的混淆后属性及方法的名称

-classobfuscationdictionary filename声明一个文本文件以提供可用的混淆后类的名称

-packageobfuscationdictionary filename声明一个文本文件以提供可用的混淆后包的名称

-overloadaggressively 声明可以使用扩展性的重载(允许只有返回值不同)

-useuniqueclassmembernames声明相同的类名称混淆后使用相同的类名,不同的也不同,该选项会稍微增大处理后的jar包。

-dontusemixedcaseclassnames 声明不生成大小写混编的类名。默认会生成

-keeppackagenames [package_filter] 声明不被混淆的包名,过滤器可以使用 * ? 及**或!

-flattenpackagehierarchy [package_name]将所有的包名重构,所有类放到指定的一个包中。

-keepattributes [attribute_filter]声明应被保留的属性,可以使用通配符。

-keepparameternames 含有指定声明方法参数或者类型的被保留

-renamesourcefileattribute [string]声明一个被写入源文件中的字符串常量

-adaptclassstrings [class_filter]声明与类名一致的字符串常量也将被混淆。

-adaptresourcefilenames [file_filter]指明将要被重命名的源文件,

-adaptresourcefilecontents [file_filter]声明内容将要被更新的源文件。

====================That's All ,Thanks! =================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐