ProGuard参数使用说明

2023-11-18

ProGuard 使用说明

本文主要是翻译proguad的官方文档,以便以后使用的时候不需要再次去看英文,每次写proguard总是那么痛苦,必须写个博客记录一下,有些地方的意思我也不懂,有注明原文!!

什么是proguard

proguard是一个用于对代码进行瘦身,优化,混淆的java类库,可以把没有用到的方法,变量,属性等自动移除,经过proguad处理的app,size会更小,运行更快,还可以增加反编译的难度。

典型应用
  • 减少android app的size,加快启动速度
  • 优化移动应用的代码,提升性能
  • 保护app不被反编译和篡改

proguard相比于其他java混淆工具的主要优势是基于模板的配置(原文:compact template-based configuration)。一条简单的命令就可以很有用。

proguard是一个命令行工具,也有图形界面使用,还可以以插件的形式加入的ant,gradle等,它已经是android sdk的一部分,只需要简单的配置就可以开启(这点开发过android的苦逼都应该知道)。

proguad 使用代码混淆来提供对反编译的基本支持。但是还是可以被反编译。如果需要深度的保护,需要使用 DexGuard。 DexGuard可以对app进行优化,混淆,还可以对string,classes,resource,resource files, asset files, and native libraries进行加密(看上去很牛逼的样子,还没有用过)

使用

进入正题,接下来学习各个命令的使用

运行proguard

java -jar proguard.jar options ...

可以在proguard发布包的lib目录下找到jar,也可以使用bin目录下的脚本来运行,一般情况下可以把参数写在 myconfig.pro中,然后运行

java -jar proguard.jar @myconfig.pro

也可以把脚本和参数合起来使用

java -jar proguard.jar @myconfig.pro -verbose

一个配置文件可以如下:

-injars       myapplication.jar 
-outjars      myapplication_out.jar 
-libraryjars  <java.home>/lib/rt.jar 
-printmapping myapplication.map 

-keep public class mypackage.MyMain { 
      public static void main(java.lang.String[]); 
}

接下来介绍各个参数

注:关于filename,class_path,filter的写法后面有解释

Input/Output Options

-include filename

递归的从给定文件中读取参数

-basedirectory directoryname

指定当前配置文件中所有路径参数的基本目录

-injars class_path

指定需要被处理r的jar(或者 aars, wars, ears, zips, apks, or directories)。在默认情况下任何非.class的文件会被原样复制到最终打包的jar。这里需要注意的是那些临时文件(如IDE产生的文件),尤其是当你直接用一个目录指定jar文件。class_path下的条目可以被过滤,详细请看filter,为了可读性,可以使用多条-injars命令

-outjars class_path

指定输出jar包的名字(或者 aars, wars, ears, zips, apks, or directories)。前面-injars 指定的jar包会被包含到输出jar包里。这个也可以使用过滤,详细请看filter
你必须避免让输出文件复写输入文件。为了可读性,可以使用多条-outjars ,如果没有指定-outjar,不会有任何jar包生成。

-libraryjars class_path

指定要被处理的程序依赖的jar(或者 aars, wars, ears, zips, apks, or directories),这些jar不会被包进output jar。这个指定的jar至少得包含程序中有被继承的类。那些只有被调用的库中的class文件不需要出现,虽然他们的出现会改善优化的结果(什么鬼, Library class files that are only called needn’t be present, although their presence can improve the results of the optimization step. )。当然这些path也是可以过滤的 ,为了可读性,可以使用多条 -libraryjars options.
请注意那些为运行proguard设置的class path,不会被用于寻找类文件,也就是说你必须显示的指定你的代码需要用到的jar路径。虽然这看上去有点麻烦,但是可以让你处理不同运行环境下的程序。比如你可以处理
j2se 的程序也可以处理android app,只要你指定合适的jar路径。

示例:

-injars       myapplication.jar 
-outjars      myapplication_out.jar 
-libraryjars  <java.home>/lib/rt.jar 
-printmapping myapplication.map 

-keep public class mypackage.MyMain { 
      public static void main(java.lang.String[]); 
}

-skipnonpubliclibraryclasses

在读取依赖的库文件时,略过非public类,来加快处理速度和减少ProGuard内存消耗 。

-dontskipnonpubliclibraryclasses

在读取依赖的库文件时,不要略过那些非public类,在4.5版本中,这是默认设置

-dontskipnonpubliclibraryclassmembers

不要忽略依赖库中的非公有的类成员,包括域和方法,proguard默认会忽略

-keepdirectories [directory_filter]

指定那些需要被保留在输出jar的文件目录,在默认情况下,这些目录会被移除来减小输出文件的size。

-target version

指定需要被处理的类文件的java版本,如1.0, 1.1, 1.2, 1.3, 1.4, 1.5 (or just 5), 1.6 (or just 6), 1.7 (or just 7), or 1.8 (or just 8)

-keep 选项

指定需要被保留的类和成员。

-keepclassmembers

指定需要被保留的类成员,如果他们的类也有被保留。比如你要保留一个序列化类中的所有成员和方法

-keepclasseswithmembers

指定保留那些含有指定类成员的类,比如你想保留所有包含main方法的类

-keepnames

指定那些需要被保留名字的类和类成员,前提是他们在被代码压缩的时候没有被移除。举个栗子,你可能希望保留那些实现了Serializable接口的类的名字

-keepclassmembernames

指定那些希望被保留的类成员的名字

-keepclasseswithmembernames

保留含有指定名字的类和类成员。

下面介绍一下类名指定的语法,这部分也是最重要的,新手往往就死在这里

首先看一下模板

[@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname
    [extends|implements [@annotationtype] classname]
[{
    [@annotationtype] [[!]public|private|protected|static|volatile|transient ...] <fields> |
                                                                      (fieldtype fieldname);
    [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> |
                                                                                           <init>(argumenttype,...) |
                                                                                           classname(argumenttype,...) |
                                                                                           (returntype methodname(argumenttype,...));
    [@annotationtype] [[!]public|private|protected|static ... ] *;
    ...
}]

方括号 : []
方括号代表里面的内容是可选的

省略号 : …
代表前面被指定的条目可以有任意多个。

竖线 : |
划分两个选项

括号 : ()
代表整体

缩进
用于说明意图

空格
没有意义

  • 关键字class 可以指向任何接口或类。interface 关键字只能指向接口,enum 只能指向枚举 ,接口或者枚举前面的!表示相对应的非枚举或者接口。

  • 每个classname 都必须是全路径指定,比如:java.lang.String 内部类使用美元符”$”分开,比如: java.lang.Thread$State 类名可以使用包含以下通配符的正则表达式:

    ? 任意匹配类名中的一个字符,但是不匹配包名分隔符。例如 “mypackage.Test?” 匹配”mypackage.Test1” 和 “mypackage.Test2”,不匹配 “mypackage.Test12”.

    *匹配类名的任何部分除了包名分隔符,例如”mypackage.*Test*”匹配 “mypackage.Test” 和 “mypackage.YourTestApplication”,但是不匹配 “mypackage.mysubpackage.MyTest”. 或者更通俗的讲, “mypackage.*” 匹配所有 “mypackage”包里的内容,但是不匹配它子包里的内容.

    ** 匹配所有类名的所有部分,包括报名分隔符。

    • extendimplements 符号用于使用统配付来限定类. 他们效果是一样的,指定只有继承或者实现指定的类和接口。

    • @ 符号用于限定那些被指定注解符号标注的类和类成员,注解符的指定方法和类名一样

    • 域和方法的指定更像java语言,除了方法参数中没有参数名。表达式可以包含以下通配符:

    < init > 匹配任何构造函数

    < fields > 匹配任何域

    < methods > 匹配任何方法

    * 匹配任何方法和域

    注意: 上面的所有统配符都没有返回值,只有< init >有参数列表.

    方法和域还可以用正则表示指定,可以使用的通配符如下:

    ? 任意匹配方法名中的单个字符

    * 匹配方法命中的任意部分

    数据类型描述可以使用以下通配符:

    % 匹配任何原生类型 (“boolean”, “int”, etc, but not “void”).

    ? 任意匹配单个字符

    * 匹配类名的任何部分除了包名分隔符

    ** 匹配所有类名的所有部分,包括报名分隔符。

    *** 匹配任何类型,包括原生和非原生,数组和非数组

    匹配任意参数个数
    ?* 和 ** 永远不会匹配原生类型,而且只有 **** 匹配数组类型。举个栗子:”** get*()” 匹配
    “java.lang.Object getObject()” 但是不匹配”float getFloat()” 也不匹配”java.lang.Object[] getObjects()”

  • 构造函数可以使用段类名(不包含包名)

  • 类访问修饰符(public private static)一般用来限制统配类和类成员. 他们限定指定的类必须拥有指定的访问修饰符.一个前置的!表示该修饰符没有被设置

可以组合多个标志 (e.g. public static). 表示两个条件都要满足

ProGuard 还支持一些的其他编译器会用到的修饰符 synthetic, bridge, 和varargs.

-printseeds

将匹配的类和成员全部打印到文件或者输出。这个可以用来验证自己需要保留的类有没有成功保留

Shrinking options

-dontshrink

不压缩类文件。默认情况下会压缩所有的类文件,除了那些用keep声明和被这些类依赖的class

-printusage [filename]

将没有用到的code打印到文件或者后台

-whyareyoukeeping class_specification

将那些被保留的类的原因打印出来

Optimization options

-dontoptimize

不优化代码,默认优化

-optimizations optimization_filter

指定需要被enable和disable的优化项目。

-optimizationpasses n

指定优化的pass数目,默认是1,多个pass可以提升优化效果. 如果在一个优化pass结束后,没有发现被提升的项目,优化就结束

-assumenosideeffects class_specification

指定那些没有任何副作用的方法,也就是说这些方法没有实际用处,移除也没关系,比如log方法,请谨慎使用该参数,除非你知道你在做什么

-allowaccessmodification

设置该参数后,允许proguard在优化过程中扩大访问权限。这样可以提升优化效果。请不要讲此选项应用在
作为lib使用的code中,因为这可能会将那些不希望被访问的代码变的可以被访问

-mergeinterfacesaggressively

设置该参数后,允许interface被merge,即使他们的实现类没有全部实现他们。这样可以通过减少class的数量来减小输出结果的size。java 二进制规范是允许这样做的 (cfr. The Java Language Specification, Third Edition, Section 13.5.3), 虽然java语言不允许这样做(cfr. The Java Language Specification, Third Edition, Section 8.1.4). 设置这个选项会在默写虚拟机上降低处理的性能,因为一些高级的JIT偏向于更少的类实现更多的接口,更坏的是,一些虚拟机可能无法处理被优化过的代码。

Obfuscation options
(代码混淆选项)

-dontobfuscate

不混淆代码,默认混淆

-printmapping [filename]

将mapping 打印到文件或后台

-applymapping filename

使用已有的mapping文件来混淆代码

-obfuscationdictionary filename

指定希望被用做指定类和类成员混淆后新名字的列表

-classobfuscationdictionary filename

指定一个文件,里面的所有名字将被用作混淆后类的名字

-packageobfuscationdictionary filename

指定一个文件,里面的所有名字将被用作混淆后包的名字

-overloadaggressively

这只这个选项后,多个方法和域会使用同一个名字,只要他们的参数和返回类型不一样。这样可以减少优化后的size

-useuniqueclassmembernames

如果类成员在混淆前拥有相同的名字,那么混淆后也使用相同的名字,如果混淆前拥有不同的名字,那么混淆后也是用不同的名字。如果不设置这个参数,那么更多的成员可以被映射到同一个名字。如 ‘a’, ‘b’, 等。所以使用这个参数会稍微增加最后的size,但是这个可以确保被保存的混淆后的名字在后面的处理中被尊重。

-dontusemixedcaseclassnames

不生成大小写混合的类名。在默认情况下,混淆后的类名会包含大小写。但是当你在那些大小写不敏感的平台,比如windows下解压混淆后的jar,解包工具会将那些相似名字的类复写。

-keeppackagenames [package_filter]

不混淆指定的包名,包名用逗号分开。可以包含? * ,** 等通配符,也可以用!前置

-flattenpackagehierarchy [package_name]

将那些被重新命名的包重新打包,他们将会被移动到同一个父包里。如果不指定包名或者是空字串,那么他们会被打包到根包。

-repackageclasses [package_name]

将那些被重新命名的类重新打包,如果没有指定参数或者是空字串,那么包会被完全删除。这个参数会覆盖 -flattenpackagehierarchy参数。

-keepattributes [attribute_filter]

指定需要被保留的属性,可以使用多条 -keepattributes命令。多条属性用逗号分开,也可以使用? * ** 通配符,也可以使用!。例如,当你处理一个lib的时候至少得保留Exceptions, InnerClasses, and Signature 属性。当你生成混淆stack traces时应该保留SourceFile 和LineNumberTable 。最后你可以保留annotations 如果你的代码依赖他们。

-keepparameternames

保留那些需要被保留的方法的参数名字。这个选项事实上保留的是LocalVariableTable 和LocalVariableTypeTable这两个debug属性的修剪版本。这在处理lib的时候很有用。有些IDE可以用这些信息去协助开发者,比如工具提示和自动补全。

-renamesourcefileattribute [string]

指定一个放在类文件SourceFile 属性的String。这些属性必须放在开头,所以这也必须用-keepattributes 显示的指定。

-adaptclassstrings [class_filter]

指定那些对应到某个class name的String常量也要被混淆。如果没有设置过滤,所有对应于某个class name的string都要被适配。如果有设置过滤,只适配匹配过滤的string。举个例子,如果你的代码中有大量对应class的硬编码的string,然后你又不想保留他们的名字,就可以可以使用这个选项。

-adaptresourcefilenames [file_filter]

指定对资源文件重命名的时候,使用对应class被混淆后的名字。如果没有指定过滤,所有资源文件都会被重命名,如果设置过滤,只有匹配的资源文件才会被过滤

-adaptresourcefilecontents [file_filter]

指定内容需要被更新的资源文件。任何在这些资源文件中被提及的class name都要被重名,基于那些相应的类被混淆后的名字。如果没有设置过滤,所有资源文件的内容将被更新。资源文件使用系统默认的字符集来解析和写入。你可以通过设置环境变量 LANG或者java 系统属性 file.encoding来更改。
警告: 你可能只希望将这个选项应用于text文件,因为解析和适配二进制文件会导致一些意想不到的问题,所以请确保你的指定的file足够精确.

Preverification options
(预校验选项)

-dontpreverify

不对类文件进行预校验。默认情况下,如果类文件的目标是Java ME或者不低于java 6,都会进行预校验。
对于Java ME,预校验是要求的,所以你需要运行一个外部的预校验过程在你处理过的代码上如果你设置了这个选项。对于 java 6 这是一个可选的选项,但是在java 7 这是被要求的。只有在andriod中这是不被强制要求的,所以你可以关闭这个选项。

-microedition

指定被处理的class file是指向Java ME的。这样预校验就会适当的添加StackMap属性,这个和默认的StackMapTable属性不一样,因为这是对于Java SE来说。

General options
(一般选项)

-verbose

在处理过程中输出更详细的信息,如果在处理过程中出现异常,将会输出完整的调用栈,而不是只有错误信息

-dontnote [class_filter]

不要输出配置文件的潜在错误和遗漏,比如类名拼写错误或者缺少一些有用的选项。可选的过滤器是一个正则表达式;ProGuard 不会打印那些被过滤器匹配成功的类名的信息。

-dontwarn [class_filter]

完全不要警告unresolved references 和 其他重要的问题.可选的过滤器是一个正则表达式。 ProGuard 不会打印那些被过滤器匹配的成功的类的警告信息。忽略警告是非常危险的,举个例子,如果 unresolved classes or class members是确实被需要的,那么代码可能无法正常工作,所以请小心使用

-ignorewarnings

打印任何关于unresolved references 和其他重要问题的警告,但是会继续处理下去。忽略警告是危险的。举个例子如果 unresolved classes or class members是确实被需要的,那么代码可能无法正常工作,所以请小心使用

-printconfiguration [filename]

将配置文件的内容,包括被替换的变量和引入的文件打印到后台或者文件。

-dump [filename]

在任何处理步骤后,输出类文件的内部结构。可以输出到后台或者文件。比如,你可能希望打印出一个jar包的所有内容。

Class paths
(类路径)

ProGuard 接受一个通用的类路径来表示输入文件和输出文件。一个类路径可以有好几个类组成,由分隔符分开 (e.g. ‘:’ on Unix, or ‘;’ on Windows platforms),出现顺序决定 了在出现重复类时候的优先级。

输入文件和输出文件可以是以下形式:

  • 类文件或资源文件
  • apk
  • jar
  • aar
  • war
  • ear
  • zip
  • 目录

直接指定的类文件和资源的路径会被忽略,所以类文件应该是一个jar ,aar, a war, ear, zip, 或者目录的一部分。另外,类路径应该没有额外的前缀。

关于在打包的时候的选项,可以参考一下例子

restructure output archives.

关于文件和目录的命名可以参考file names

另外 ProGuard还可以基于类文件的完整相对名字来过滤类路径和他们的内容。每个类路径可以被最多7个文件过滤器跟着,这些过滤器用圆括号括起来,并用分号分开:

  • 用于aar的过滤器,
  • 用于apk 的过滤器,
  • 用于zip 的过滤器,
  • 用于ear 的过滤器,
  • 用于war 的过滤器,
  • 用于jar 的过滤器,
  • 用于所有类文件名和资源文件名的过滤器.

如果少于7个过滤器被指定,他们会被认为是后者的过滤器。任何空的过滤器会被忽略。更正式,一个被过滤的class path可以如下:

classpathentry([[[[[[aarfilter;]apkfilter;]zipfilter;]earfilter;]warfilter;]jarfilter;]filefilter)

方括号的意思是里面的内容是可选的

例如, “rt.jar(java/.class,javax/.class)” 匹配rt.jar中所有在java和javax目录下的class文件

例如, “input.jar(!.gif,images/)” 匹配在input.jar里images目录下所有文件,除了.gif文件

不同的过滤器会被应用到所有相应的文件类型,不管他们在jar中的嵌套层次;他们是正交的(orthogonal)

例如, “input.war(lib/.jar,support/.jar;.class,.gif)” 只关注input war 里lib目录下的jar和suppor目录下的jar,然后会匹配所有遇到的class文件和gif文件

File names

ProGuard 接受文件和目录的绝对路径和相对路径。相对路径的解释如下:
如果设置了基准目录,则就相对基准目录,否则就相对与配置文件的路径,其他任何情况就相对与工作目录。名字可以包含java系统属性(或者Ant 属性,如果使用Ant),用’<’和’>’分隔。属性会被自动替换成他们对应点值。

那些带有特殊字符的名字像空格和括号,必须用单引号或者双引号括起来。每个在列表中的名字必须用引号单独的括起来。引号本身需要escaped 当使用命令行的时候,来避免被shell gobbled。

例如,在命令行,你可以使用’-injars “myprogram.jar”:”/your directory/your program.jar”’

File filters

像通用过滤器,文件过滤器是一个包含通配符,用逗号分开的名字列表。只有名字匹配了过滤的的文件才会被读取或者写入。支持以下通配符:

? 匹配任何单个字符
* 匹配文件名的任何部分,除了路径分隔符
** 匹配文件名的任何部分,包含任意个文件分隔符

例如, “java/.class,javax/.class” 匹配所有在java和javax里的class文件。

此外, 文件名字之前可以加!,表示排除这个文件名

例如,”!**.gif,images/**”匹配所有在images目录下除了gif文件之外的所有文件

Filters

ProGuard提供了很多带有过滤器的选项,在配置的各个方面:文件名,目录,类,包,属性,优化等。 过滤器是包含了一串用逗号分开的含有通配符的名字列表。只有匹配的名字才可以通过过滤器。支持的通配符依赖于那些被过滤名字的类型,但是以下的通配符是典型的:
A filter is a list of comma-separated names that can contain wildcards. Only names that match an item on the list pass the filter. The supported wildcards depend on the type of names for which the filter is being used, but the following wildcards are typical:

? 匹配任何单个字符
* 匹配文件名的任何部分,除了路径分隔符

此外, 名字还可以用!做前缀来用于在后面的匹配中将该名字排除。所以一个名字如果匹配一个过滤器,它是被拒绝或者接受取决于那个过滤器的条目是不是以!开头。如果名字不匹配这个过滤条目,就继续匹配接下来的条目。如果不匹配任何个条目,它是被拒绝还是接受要取决于最后的过滤条目是否以!开头

例如, “!foobar,*bar” 匹配所有以bar结尾的名字,除了footbar。

Keep option modifiers

includedescriptorclasses

如果某些方法和域被-keep保留,那么这些方法和域的类型描述符中的任何类也要被保留。这在保留native方法名字时很有用,用来确保native方法的参数类型不会被重命名。

allowshrinking

指定被-keep保留的条目可以被压缩,即使他们不得不被保留。意思是,条目可能在压缩步骤中被移除,但是如果他们是必须的,他们可以不被优化或者混淆。

allowoptimization

指定被-keep的条目可以被优化,即使他们必须被保留。意思是条目可能在优化步骤中被改变,但是他们可以不被移除或者混淆。

allowobfuscation

指定被-keep的条目可以被混淆,即使他们必须被保留。意思是,条目可能在混淆步骤中被改名,但是他们可以不被移除和优化。

Overview of keep options

各种各样的用于压缩和混淆的-keep选项 在刚开始可能让人感觉混乱,但是却是有规律的。下表罗列了他们之间的关系:

Keep From being removed or renamed From being renamed
Classes and class members -keep -keepnames
Class members only -keepclassmembers -keepclassmembernames
Classes and class members, if class members present -keepclasseswithmembers -keepclasseswithmembernames

每一个-keep 选项后面会跟着一个类和类成员的定义,-keep将被引用到这些类和类成员中。

如果你不确定你需要哪一个选项,你应该简单的使用-keep。它会确保指定的类好成员不会在压缩步骤中被移除,和在混淆步骤中被改名。

如果你指定类的时候没有指定类成员,ProGuard只会保留类和它的无参构造函数。

如果你指定了一个方法,ProGuard只会保留这个方法,它的代码任然会被优化和适配。

在android中的应用

Android activity

-injars      bin/classes 
-outjars     bin/classes-processed.jar 
-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar 

-dontpreverify 
-repackageclasses '' 
-allowaccessmodification 
-optimizations !code/simplification/arithmetic 
-keep public class mypackage.MyActivity 

一个完整的Android程序

标准的Android SDK build过程已经整合了Proguard(with Ant, Gradle, Android Studio and Eclipse).你只要将project.properties中的“proguard.config=…..”注释去掉就可以。

Notes:

  • 一旦遇到问题,你可能想要检查一下配置文件.

  • Android SDK revision 20 和后面的版本在配置文件的开启proguad上有一点区别, ${sdk.dir}/tools/proguard/proguard-android-optimize.txt 代替默认的 ${sdk.dir}/tools/proguard/proguard-android.txt.

  • 编译过程已经设置了必要的jar,输入jar和输出jar,不需要再次设置.
    -如果你看到关于missing referenced classes的警告:这太常见了,你可以看看 Troubleshooting shooting部分。

如果你正在从scratch构建编译过程:这些选项会压缩,优化,混淆编译过的classes和外部依赖库的所有public activities, services, broadcast receivers and content providers:

-injars      bin/classes 
-injars      libs 
-outjars     bin/classes-processed.jar 
-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar 

-dontpreverify 
-repackageclasses '' 
-allowaccessmodification 
-optimizations !code/simplification/arithmetic 
-keepattributes *Annotation* 

-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.view.View { 
      public <init>(android.content.Context); 
      public <init>(android.content.Context, android.util.AttributeSet); 
      public <init>(android.content.Context, android.util.AttributeSet, int); 
      public void set*(...); 
} 

-keepclasseswithmembers class * { 
    public <init>(android.content.Context, android.util.AttributeSet); 
} 

-keepclasseswithmembers class * { 
    public <init>(android.content.Context, android.util.AttributeSet, int); 
} 

-keepclassmembers class * extends android.content.Context { 
    public void *(android.view.View); 
    public void *(android.view.MenuItem); 
} 

-keepclassmembers class * implements android.os.Parcelable { 
    static ** CREATOR; 
} 

-keepclassmembers class **.R$* { 
    public static <fields>; 
} 

-keepclassmembers class * { 
    @android.webkit.JavascriptInterface <methods>; 
} 

最重要的是,我们要保留那些可能被AndroidManifest.xml引用的基础类。如果你的manifest包含其他类和方法,你也必须这样指定。

我们保留注解,因为他们可能被客制化的remoteview使用。

我们保留任何客制化的View的扩展和其他拥有典型的构造函数的类,因为他们可能被XML布局文件引用。

我们保留在自定义的Context 扩展中onClick处理方法,因为他们可能被xml布局文件引用。

我们也保留那些Parcelable 实现类重点被要求的静态域,以为他们可能被introspection访问

我们保留自动生成的R类的被引用的内部类的静态域,以防万一你的代码被introspection访问.要注意的是,编译器已经内联了原始类型的域,所以Proguard可以完全移除这些类,因为这些类不会被引用所以也不会被需求。

最后,我们保留注解的javascript借口方法,这样他们可以通过他们的原始名字被访问。那些被有被注解的JavaScript方法(target api小于4。2)也需要被手动注解。

如果你使用另加的Google Api,你就需要指定那些,举个例子:

-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar

如果你正在使用可选的GoogleIf License Verification Library,你可以将它的code和你的code一起混淆,为了能让库正常工作,你必须保留它的ILicensingService 接口:

-keep public interface com.android.vending.licensing.ILicensingService

如果你正在使用Android的兼容包,你应该添加以下命令行,让ProGuard知道,库引用一些类,可能不是在所有版本的api中都可用。

-dontwarn android.support.** 

未完待续…

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ProGuard参数使用说明 的相关文章

随机推荐

  • OpenCV(五)——运动目标识别

    课程一览 目录 1 摄像头调用 2 视频的读取与保存 3 帧差法 4 光流法 5 背景减除法
  • ERROR: FPM initialization failed

    出错的原因主要是 usr local php5 sbin php fpm配置错误 仔细检查下 我的错误就是group www这里少了 号 所以出错了 root localhost usr local php5 sbin php fpm PH
  • 服务器系统巡查登记表,信息设备巡检记录表

    信息设备巡检记录表 由会员分享 可在线阅读 更多相关 信息设备巡检记录表 2页珍藏版 请在人人文库网上搜索 1 信息设备巡检记录表 检査人 检査时间 年月日 一 机房环境尺周边设缶 枪杏顶 结论 情况摘要 枪杏顶 结论 情况摘要 溫度 正常
  • MCS-51 汇编指令集(J开头的指令)

    MCS 51系列单片机指令以J开头的指令有8条 分别为 JB bit rel JBC bit rel JC rel JMP A DPTR JNB bit rel JNC rel JNZ rel JZ rel 1 JB bit rel 指令名
  • 计算机设置桌面文件夹,win10电脑怎么更改桌面文件夹路径

    win10电脑怎么更改桌面文件夹路径 我们在使用电脑的时候 在桌面上保存的文件一般都默认在C盘 今天小编跟大家分享下win10电脑怎么更改桌面文件夹路径 具体如下 1 首先我们打开电脑 找到 我的电脑 双击打开 2 进入主界面之后我们选中
  • cocos creator主程入门教程(九)—— 瓦片地图

    这一篇介绍瓦片地图 在开发模拟经营类游戏 SLG类游戏 RPG游戏 都会使用到瓦片地图 瓦片地图地面是通过一个个地砖拼起来的 又分为45度角和90度角两种 45度角俗称2 5D 每个格子都是菱形 而90度角每个格子都是正方形 瓦片地图一般包
  • dlib的安装

    由于需要人脸识别 所以需要安装opencv和dlib OpenCV的安装很顺利 实例也跑的很正常 但dlib的安装却出现了很多坑 而且国内的解决方法都是复制粘贴 一点营养都没有 查了国外资料 终于解决 记录一下 首先是需要安装 以下依赖 b
  • 【C语言】指针和数组的深入理解(第四期)

    篮球哥温馨提示 编程的同时不要忘记锻炼哦 上了编程的贼船 就做快乐的海盗 目录 1 数组参数和指针参数 1 1 一维数组传参 1 2 一级指针传参 1 3 二维数组参数和二级指针参数 1 4 野指针的问题 2 函数指针 3 函数指针数组 4
  • C#创建一个收费接口Charge,其中有一个方法charge();创建另一个收费接口Play,其中有一个方法play()。声明类Bus来实现接口Charge,对于Bus中的charge()实现为输出“

    创建一个收费接口Charge 其中有一个方法charge 创建另一个收费接口Play 其中有一个方法play 声明类Bus来实现接口Charge 对于Bus中的charge 实现为输出 公共汽车 1元 张 不计公里数 声明类Taxi来实现接
  • pythonmap和list_python map和list的区别是什么

    一 结构特点 List是存储单列数据的集合 Map是存储键值对这样的双列数据的集合 List中存储的数据是有顺序的 并且值允许重复 Map中存储的数据是无序的 它的键是不允许重复的 但是值是允许重复的 二 实现类 List接口有三个实现类
  • webpack4.+的使用(一)(webpack的基本使用)

    webpack4 的使用 一 一 webpack的基本使用 1 安装和卸载webpack开发依赖的命令分别为 npm install webpack g和npm uninstall webpack g npm命令是在安装了node js后才
  • SpringBoot 中LocalDateTime格式化日期

    简介 很多时候日期格式输出是这样的 2018 10 09T17 39 07 097 中间有个T 尴尬 是的我们需要去掉这个T 这方法是springboot封装好了的 我们直接使用即可 普通的配置我就不贴了 一 日期格式化输出 code 1
  • unity 物体自动旋转

    using UnityEngine public class AutoRotation MonoBehaviour Tooltip Angular velocity in degrees per seconds public float d
  • 21. Merge Two Sorted Lists

    题目 Merge two sorted linked lists and return it as a new list The new list should be made by splicing together the nodes
  • TensorRT学习(二)通过C++使用

    本文源于学习TensorRT文档 TensorRT Developer Guide 第2章 WORKING WITH TENSORRT USING THE C API 的理解 一 TensorRT实例化对象 使用TensorRT进行推理需要
  • 为什么要接入高防IP,到底有什么作用呢

    首先我们要了解什么是高防IP DDOS高防IP是为了应对互联网的DDOS攻击而产生的一款付费增值产品 根据不同的业务接入的方法也不同 在开通这款DDOS高防IP时服务商会给到对应的高防IP作为对外IP和业务IP使用 游戏业务就需要将之前配置
  • rknn-toolkit安装的一点感想

    rknn toolkit装了好多次 总是会报错 终于尝试出了一个版本可以用的 注意windows和linux上都能用 rknn toolkit v1 7 1 cuda 10 1 python 3 6 pytorch 1 5 1 opencv
  • Ubuntu Hadoop分布式部署

    Ubuntu Hadoop分布式部署 1 vim usr local hadoop 3 2 2 etc hadoop hadoop env sh usr local hadoop 3 2 2为Hadoop安装目录 export JAVA H
  • Android-使用WebView视图显示网页

    简介 Android提供了WebView组件 相关类为android webkit WebView android webkit WebViewClient 表面上来看 这个组件与普通的ImageView差不多 但实际上 这个组件的功能要强
  • ProGuard参数使用说明

    ProGuard 使用说明 本文主要是翻译proguad的官方文档 以便以后使用的时候不需要再次去看英文 每次写proguard总是那么痛苦 必须写个博客记录一下 有些地方的意思我也不懂 有注明原文 什么是proguard proguard