Androidproguard详解
发表时间:2020-10-19
发布人:葵宇科技
浏览次数:38
简介
Java代码是异常轻易反编译的。为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。
ProGuard是一个混淆代码的开源项目。它的重要感化就是混淆,当然它还能对字节码进行缩减体积、优化等,但那些对于我们来说都算是次要的功能。官网网址是:
http://proguard.sourceforge.net/。
详解
1、道理
Java 是一种跨平台的、解释型说话,Java 源代码编译成中心”字节码”存储于 class 文件中。因为跨平台的须要,Java 字节码中包含了很多源代码信息,如变量名、办法名,并且经由过程这些名称来拜访变量和办法,这些符号带有很多语义信息,很轻易被反编译成 Java 源代码。为了防止这种现象,我们可以应用 Java 混淆器对 Java 字节码进行混淆。
混淆就是对宣布出去的法度榜样进行从新组织和处理,使得处理后的代码与处理前代码完成雷同的功能,而混淆后的代码很难被反编译,即使反编译成功也很可贵出法度榜样的┞锋正语义。被混淆过的法度榜样代码,仍然遵守本来的档案格局和指令集,履行结不雅也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏响应的函数名和法度榜样注释的况下,即使被反编译,也将难以浏览。同时混淆是弗成逆的,在混淆的过程一一些不影响正常运行的信息将永远损掉,这些信息的损掉使法度榜样变得加倍难以懂得。
混淆器的感化不仅仅是保护代码,它也有精简编译后法度榜样大年夜小的感化。因为以上介绍的缩短变量和函数名以及损掉部分信息的原因, 编译后 jar 文件体积大年夜约能削减25% ,这对当前费用较贵的无线收集传输是有必定意义的。
2、语法
-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} 设置源文件中给定的字符串常量
demo 实例
-ignorewarnings # 忽视警告,避免打包时某些警告出现
-optimizationpasses 5 # 指定代码的紧缩级别
-dontusemixedcaseclassnames # 是否应用大年夜小写混淆
-dontskipnonpubliclibraryclasses # 是否混淆第三方jar
-dontpreverify # 混淆时是否做预校验
-verbose # 混淆时是否记录日记
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采取的算法
-libraryjars libs/treecore.jar
-dontwarn android.support.v4.** #缺省proguard 会检查每一个引用是否精确,然则第三方库琅绫擎往往有些不会用到的类,没有精确引用。如不雅不设备的话,体系就会报错。
-dontwarn android.os.**
-keep class android.support.v4.** { *; } # 保持哪些类不被混淆
-keep class com.baidu.** { *; }
-keep class vi.com.gdi.bgl.android.**{*;}
-keep class android.os.**{*;}
-keep interface android.support.v4.app.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment
-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.support.v4.widget
-keep public class * extends com.sqlcrypt.database
-keep public class * extends com.sqlcrypt.database.sqlite
-keep public class * extends com.treecore.**
-keep public class * extends de.greenrobot.dao.**
-keepclasseswithmembernames class * { # 保持 native 办法不被混淆
native <methods>;
}
-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.app.Activity { //保持类成员
public void *(android.view.View);
}
-keepclassmembers enum * { # 保持列举 enum 类不被混淆
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable { # 保持 Parcelable 不被混淆
public static final android.os.Parcelable$Creator *;
}
-keep class MyClass; # 保持本身定义的类不被混淆
3、文件
在release模式下打包apk时会主动运行ProGuard,这里的release模式指的是经由过程ant release敕令或eclipse project->android tools->export signed(unsigned)
application package生成apk。
在debug模式下为了更快调试并不会调用proguard。
如不雅是ant敕令打包apk,proguard信息文件会保存于<project_root>/bin/proguard文件夹内;
如不雅用eclipse export敕令打包,会在<project_root>/proguard文件夹内。个中包含以下文件:
mapping.txt
表示混淆前后代码的对比表,这个文件异常重要。如不雅你的代码混淆后会产生bug的话,log提示中是混淆后的代码,欲望定位到源代码的话就可以根据mapping.txt反推。
每次宣布都要保存它便利该版本出现问题时调出日记进行排查,它可以根据版本号或是宣布时光定名来保存或是放绝代码版本控制中。
dump.txt
描述apk内所有class文件的内部构造。
seeds.txt
列出了没有被混淆的类和成员。
usage.txt
列出了源代码中被删除在apk中不存在的代码。
4、不克不及混淆的代码
顾名思义,不克不及混淆代码,不然会掉足。
1、放射的处所
2、体系接口
3、Jni接口
4、
android.app.backup.BackupAgentHelper
android.preference.Preference
com.android.vending.licensing.ILicensingService
……
5、bug(常见缺点)
1、Proguard returned with error code 1. See console
1、更新proguard版本
2、android-support-v4 一向行混淆
3、添加缺乏响应的库
2、应用gson包解析数据时,出现missing type parameter异常
1、在 proguard.cfg中添加
-dontobfuscate -dontoptimize
2、在 proguard.cfg中添加
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }3、类型转换缺点
-keepattributes Signature4、空指针异常
混淆过滤掉落相干类与办法
5、安卓代码混淆与反射冲突,地图无法显示等问题解决及反编译办法,安卓反编译
此前的代码混淆,因为并没有效到反射,所以惯例的代码混淆方法一遍就能经由过程,而此项目中某些类应用到了反射机制(本人的┞封个项目中有即时通信功能,所以有神情类资本,是以须要经由过程反射由文件名找到神情资本id),当由文件名去寻找资本id时就报空指针异常了,期初我并不知道什么原因,经由过程反编译已经混淆的apk,一步一步寻找到掉足的处所,才恍然大年夜悟,恰是反射那一步出现了问题:Field field = R.drawable.class.getDeclaredField(name);走到这一步就挂了,法度榜样直接崩溃。
解决办法:
1.在proguard.cfg文件中,将反射用到的类中的变量不被混淆:
如:-keep public class com.byl.bean.Expressions { *; },表示Expressions 这个类及类中的所有变量及办法不被混淆,留意要写全路径;
2.过滤泛型:-keepattributes Signature
3.最重要的一点:保持R文件不被混淆,不然,你的反射是获取不到资本id的:-keep class **.R$* {*;}
弥补一下:上个问题解决后,接下来竽暌怪碰到了一个问题就是混淆后,地图无法正常应用了,博主应用的是百度地图,在proguard.cfg也已经写清楚明了:
-keep class com.baidu.** {*;}
-keep class vi.com.** {*;}
6、android.provider.Settings$Global
# Project target.
target=android-19
7、java.lang.reflect.UndeclaredThrowableException
-keep interface com.dev.impl.**
8、内存溢出和无法写入客栈
javaOptions in proguard := Seq(...)or
javaOptions in (Proguard, proguard) := Seq(...)
9、Error: Unable to access jarfile ..\lib\proguard.jar
路径问题
10、java.lang.NoSuchMethodError
没有相干办法,办法被混淆了,混淆过滤掉落相干办法便可。11、专业网站bug解决办法
http://proguard.sourceforge.net/index.html#manual/troubleshooting.html
总结
有了混淆技巧,代码再也不消担心被偷了…








