android开发为什么要进相混淆?
Android开发使用Java作为开发语言,Java代码是非常容易反编译的。为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。ProGuard是一个混淆代码的开源项目。它的主要作用就是混淆,它还能对字节码进行缩减体积、优化。
1、如何进行混淆?
(1)使用Android Studio正式打包时默认是不开启代码混淆的,如果需要开启代码混淆,首先需要在 app 模块下的build.gradle 文件中修改 minifyEnabled false 为 true。代码结构如下:
buildTypes {
debug {
buildConfigField "boolean", "LOG_DEBUG", "true"
minifyEnabled false
zipAlignEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //默认的混淆文件以及我们指定的混淆文件
}
release {
buildConfigField "boolean", "LOG_DEBUG", "false" //不显示log
minifyEnabled true //开启混淆
zipAlignEnabled true //压缩优化
shrinkResources true //移出无用资源
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //默认的混淆文件以及我们指定的混淆文件
}
因为开启混淆会使编译时间变长,所以debug模式下不开启
(2)然后在app模块下的proguard-rules.pro 文件来定义项目打包的混淆选项。
混淆配置规则
- 对于Android APP来说四大组件和Application不能混淆
- 避免混淆JSON类的构造函数,因为json转换用到了java反射
- 注解不能混淆,因为注解也用到了java反射
- 泛型不能混淆
- 避免混淆自定义控件类的get/set方法和构造函数
- java内部类的混淆需要注意,如果会被外部调用到,那么也不能混淆
- 不混淆任何包含native方法的,否则找不到本地方法。
- 避免混淆js相关的接口
- 避免混淆枚举类
- 避免混淆序列化类
- 避免混淆第三方SDK
- 避免混淆第三方框架
- 避免混淆属性动画兼容库
- 避免混淆Rxjava/RxAndroid
- 避免混淆实体类
混淆配置语法
-libraryjars class_path //应用的依赖包,如android-support-v4
-keep [,modifier,...] class_specification //不混淆某些类
-keepclassmembers [,modifier,...] class_specification //不混淆类的成员
-keepclasseswithmembers [,modifier,...] class_specification //不混淆类及其成员
-keepnames class_specification //不混淆类及其成员名
-keepclassmembernames class_specification //不混淆类的成员名
-keepclasseswithmembernames class_specification //不混淆类及其成员名
-assumenosideeffects class_specification //假设调用不产生任何影响,在proguard代码优化时会将该调用remove掉。如system.out.println和Log.v等等
-dontwarn [class_filter] //不提示warnning
Android app代码混淆配置的基础配置
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames # 是否使用大小写混合
-dontpreverify # 混淆时是否做预校验
-verbose # 混淆时是否记录日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法
-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.app.backup.BackupAgentHelper # 保持哪些类不被混淆
-keep public class * extends android.preference.Preference # 保持哪些类不被混淆
-keep public class * extends android.support.v4.**
-keep public class com.android.vending.licensing.ILicensingService
-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 *;
}
# 过滤注解
-keepattributes *Annotation*
-keep class * extends java.lang.annotation.Annotation { *; }
-keep interface * extends java.lang.annotation.Annotation { *; }
# 过滤泛型
-keepattributes Signature
以上只是基础配置,其他的需按项目需要进行配置,例如项目中用到的实体类、第三方库、第三方jar包的混淆配置
#----------1.实体类----------------------------------
#保持bean目录下文件不被混淆
-keep class com.chinalife.chinalifeinvestment_oa.been.** {*;}
#-----------2.第三方引用-------------------------------
#百度地图
-dontwarn com.baidu.**
-keep class com.baidu.**{*; }
# ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
# Gson
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.** {*;}
-keep class com.google.**{*;}
#------------第三方jar包-----------------------------
-dontwarn com.unionpay.**
-keep class com.unionpay.** { *; }
-dontwarn livenessLib.**
-libraryjars libs/MGFaceppSDK-0.4.7.aar
-keep class android.support.v7.widget.RecyclerView {*;}
#忽略警告
-ignorewarnings
对于第三方可以直接去官网找它的混淆配置
2、Apk反编译得到Java源代码:
1.下载工具dex2jar和jd-gui ,解压
2.将要反编译的APK后缀名改为.rar或者 .zip
3.解压,得到其中的classes.dex文件(它就是java文件编译再通过dx工具打包而成的),将获取到classes.dex放到之前解压出来的工具dex2jar-0.0.9.15 文件夹内
4.在命令行下定位到dex2jar.bat所在目录,输入cd 路径;再输入dex2jar.bat classes.dex,出现done会在该目录下会生成一个classes_dex2jar.jar的文件
5.然后打开工具jd-gui文件夹里的jd-gui.exe,之后用该工具打开之前生成的classes_dex2jar.jar文件,便可以看到源码了,被混淆过的(类文件名称以及里面的方法名称都会以a,b,c....之类的样式命名)