proguard混淆

为了防止开发APP的重要code 被泄露,我们往往需要混淆(Obfuscation code ), 也就是把方法,字段,包和类这些java 元素的名称改成无意义的名称,这样代码结构没有变化,还可以运行,但是想弄懂代码的架构却很难。 proguard 就是这样的混淆工具,它可以分析一组class 的结构,根据用户的配置,然后把这些class 文件的可以混淆java 元素名混淆掉。在分析class 的,同时他还有其他两个功能,删除无效代码(Shrinking 收缩),和代码进行优化 (Optimization Options)。

缺省情况下,proguard 会混淆所有代码,但是有些情况我们是不能改变java 元素的名称,否则就会这样就会导致程序出错。例如,用到反射的地方,我们代码依赖于系统的接口,比如被系统代码调用的回调方法,这种情况最复杂。这就需要我们在proguard-rules文件中告诉proguard 哪些java 元素是不能混淆的。

1. ProGuard配置

ProGuard关键字

保留选项(配置不进行处理的内容)

-keep {Modifier} {class_specification} 保留类和类中的成员,防止它们被混淆或移除。
-keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好
-keepclasseswithmembers {class_specification} 保留类和类中的成员,防止它们被混淆或移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。
-keepnames {class_specification} 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。
-keepclassmembernames {class_specification} 只保留类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。
-keepclasseswithmembernames {class_specification} 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。

压缩

-dontshrink 不压缩输入的类文件
-whyareyoukeeping {class_specification}

优化

-dontoptimize 不优化输入的类文件
-assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用
-allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员

混淆

-dontobfuscate 不混淆输入的类文件
-obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称
-overloadaggressively 混淆时应用侵入式重载
-useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆
-flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中
-repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中
-dontusemixedcaseclassnames 混淆时不会产生形形色色的类名
-keepattributes {attribute_name,…} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.
-renamesourcefileattribute {string} 设置源文件中给定的字符串常量

输出:

-printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件
-printusage {filename}

通配符

通配符 描述
<field> 匹配类中的所有字段
<method> 匹配类中的所有方法
<init> 匹配类中的所有构造函数
* 匹配任意长度字符,但不含包名分隔符(.)。比如说我们的完整类名是com.example.test.MyActivity,使用com.,或者com.exmaple.都是无法匹配的,因为无法匹配包名中的分隔符,正确的匹配方式是com.exmaple..,或者com.exmaple.test.,这些都是可以的。但如果你不写任何其它内容,只有一个*,那就表示匹配所有的东西。
** 匹配任意长度字符,并且包含包名分隔符(.)。比如proguard-android.txt中使用的-dontwarn android.support.**就可以匹配android.support包下的所有内容,包括任意长度的子包。
*** 匹配任意参数类型。比如void set()就能匹配任意传入的参数类型,* get*()就能匹配任意返回值的类型。
匹配任意长度的任意类型参数。比如void test(…)就能匹配任意void test(String a)或者是void test(int a, String b)这些方法。
  • 在android中在android Manifest文件中的activity,service,provider, receviter,等都不能进行混淆。一些在xml中配置的view也不能进行混淆,android提供的默认配置中都有。
  • keep和keepclasseswithmembers区别在于:keep关键字看到class *就认为应该将所有类名进行保留,不关心{}中的参数。而keepclasseswithmembers前提是{}的类中的成员必须存在,如果不存在则还是会混淆

不能混淆的东西

(1)Android 程序 ,下面这样代码混淆的时候要注意保留。
(2)Android系统组件,系统组件有固定的方法被系统调用。
(3) 被Android Resource 文件引用到的。名字已经固定,也不能混淆,比如自定义的View 。
(4)Android Parcelable ,需要使用android 序列化的。
(5) android.app.backup.BackupAgentHelper
(6) android.preference.Preference
(7) com.android.vending.licensing.ILicensingService
(8) Java序列化方法,系统序列化需要固定的方法。
(9) 枚举 ,系统需要处理枚举的固定方法。
(10)native 本地方法,不能修改本地方法名
(11)annotations 注释
(12)数据库驱动
(13)有些resource 文件
(14)用到反射的地方,比如调用aidl

常见问题

1、打包过程中,提示 Warning: can't find superclass or interface/ Warning: can't find referenced class等警告信息!
解决方法:
(1) 确保你的代码是否使用这个类,如果使用了,查看对应的第三方包有没有加上去,并且是否拉下来存在项目中
(2)如果该类存在,工程中确实使用了这个类,就在proguard中加上-keep class com.xx.yy.** { *;},让当前类不混淆。
(3) 确保报错的类没有在你的项目中使用到,可以使用"-dontwarn 类名正则表达式"屏蔽警告。
2、程序中使用泛型导致运行错误!
使用的泛型需要在混淆配置文件加了一个过滤泛型的语句,如下。
-keepattributes Signature

ProGuard的输出文件及用处

混淆之后,会给我们输出一些文件,在gradle方式下是在<project_dir>/build/proguard/</project_dir>目录下,ant是在<project_dir>/bin/proguard</project_dir>目录,eclipse构建在<project_dir>/proguard</project_dir>目录像。
分别有以下文件:

  • dump.txt 描述apk文件中所有类文件间的内部结构。
  • mapping.txt 列出了原始的类,方法,和字段名与混淆后代码之间的映射。
  • seeds.txt 列出了未被混淆的类和成员
  • usage.txt 列出了从apk中删除的代码

当我们发布的release版本的程序出现bug时,可以通过以上文件(特别时mapping.txt)文件找到错误原始的位置,进行bug修改。同时,可能一开始的proguard配置有错误,也可以通过错误日志,根据这些文件,找到哪些文件不应该混淆,从而修改proguard的配置。

注意:重新release编译后,这些文件会被覆盖,所以每次发布程序,最好都保存一份配置文件。一般去友盟统计等统计网站分析错误时,需要上传对应的mapping.txt才能看到错误信息对应的app原始类、方法、变量名。

proguard-android.txt 说明

# This is a configuration file for ProGuard.

# http://proguard.sourceforge.net/index.html#manual/usage.html

#混淆时不使用大小写混合类名
-dontusemixedcaseclassnames

#不跳过library中的非public的类
-dontskipnonpubliclibraryclasses

#打印混淆的详细信息
-verbose

# Optimization is turned off by default. Dex does not like code run

# through the ProGuard optimize and preverify steps (and performs some

# of these optimizations on its own).

#不进行优化,建议使用此选项,因为根据proguard-android-optimize.txt中的描述,
#优化可能会造成一些潜在风险,不能保证在所有版本的Dalvik上都正常运行。
-dontoptimize

#不进行预校验。这个预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度。
-dontpreverify

# Note that if you want to enable optimization, you cannot just

# include optimization flags in your own project configuration file;

# instead you will need to point to the

# "proguard-android-optimize.txt" file instead of this one from your

# project.properties file.

#对注解中的参数进行保留。
-keepattributes *Annotation*

#不混淆下面声明的两个类,这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。
-keep public class com.google.vending.licensing.ILicensingService

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

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native

#不混淆任何包含native方法的类的类名以及native方法名。
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.

# see http://proguard.sourceforge.net/manual/examples.html#beans

#不混淆任何一个View中的setXxx()和getXxx()方法,因为属性动画需要有相应的setter和getter的方法实现,混淆了就无法工作了
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();

}

# We want to keep methods in Activity that could be used in the XML attribute onClick

#不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick=”buttonClick”属性,
#当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了。
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations

#不混淆枚举中的values()和valueOf()方法,枚举我用的非常少
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#不混淆Parcelable实现类中的CREATOR字段,毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败
-keepclassmembers class * implements android.os.Parcelable {

  public static final android.os.Parcelable$Creator CREATOR;

}

#不混淆R文件中的所有静态字段,我们都知道R文件是通过字段来记录每个资源的id的,字段名要是被混淆了,id也就找不着了
-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library contains references to newer platform versions.

# Dont warn about those in case this app is linking against an older

# platform version.  We know about them, and they are safe.

#对android.support包下的代码不警告,因为support包中有很多代码都是在高版本中使用的,如果我们的项目指定的版本比较低在打包时就会给予警告。不过support包中所有的代码都在版本兼容性上做足了判断,因此不用担心代码会出问题,所以直接忽略警告就可以了。
-dontwarn android.support.**
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 混淆(Proguard)用法 最近项目中遇到一些混淆相关的问题,由于之前对proguard了解不多,所以每次都是面...
    于晓飞93阅读 56,668评论 38 230
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,486评论 25 707
  • 当前是有些工具比如apktool,dextojar等是可以对我们android安装包进行反编译,获得源码的。为了减...
    码农明明桑阅读 29,560评论 2 38
  • 因为项目源码安全需要,最近研究了下proguard混淆源码,在这里做一些分享。以下分享基于Android Stud...
    AndWang阅读 2,637评论 0 50
  • 那年,我们风华正貌,个个脸上洋溢着青春的气息,我们十六七岁,对于感情如此青涩,当我受命于母亲大人的奔...
    檬爱阅读 186评论 0 0