实际的产品研发中为了防止自己的劳动成果被别人窃取,混淆代码能有效防止apk文件被反编译,进而查看源代码。说来惭愧,作为互联网创业公司的我们也确实对竞品Apk反编译研究过,如果Apk混淆之后确实对理解源码的业务流程造成了困扰,这也从侧面说明了Apk混淆的重要性。
面我们将分别介绍代码混淆与资源文件混淆具体实践- 代码混淆-Progurd
下面来总结以下混淆代码的步骤:
- 在Android studio的Android项目中找到module的gradle配置文件,添加proguard配置
buildTypes {
debug {
// 显示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
//混淆
minifyEnabled false
//Zipalign优化
zipAlignEnabled true
// 移除无用的resource文件
shrinkResources true
//加载默认混淆配置文件
proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
//签名
signingConfig signingConfigs.debug
}
release {
// 不显示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
//混淆
minifyEnabled true
//Zipalign优化
zipAlignEnabled true
// 移除无用的resource文件
shrinkResources true
//加载默认混淆配置文件
proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
//签名
signingConfig signingConfigs.relealse
}
}
2.ProGuard常用语法
下面列出一些常用的语法
- -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
3.编写proguard-rules.pro文件,添加混淆配置
(1)混淆原则
1.jni方法不可混淆
2.反射用到的类不混淆(否则反射可能出现问题)
3.AndroidMainfest中的类不混淆,四大组件和Application的子类和Framework层下所有的类默认不会进行混淆
4.Parcelable的子类和Creator静态成员变量不混淆,否则会产生Android.os.BadParcelableException异常
5.使用GSON、fastjson等框架时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象
6.使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则
7.有用到WEBView的JS调用也需要保证写的接口方法不混淆
(2)第三方库的混淆原则
一般的第三方库都有自身的混淆方案,
可直接引用其自身的混淆配置即可
若无混淆配置,一般的可配置不混淆第三方库
(3)proguard混淆基本语法
#忽略警告,避免打包时某些警告出现
-ignorewarnings
#指定代码的压缩级别 设置混淆的压缩比率 0 ~ 7
-optimizationpasses 5
#是否使用大小写混合
-dontusemixedcaseclassnames
#如果应用程序引入的有jar包,并且想混淆jar包里面的class
-dontskipnonpubliclibraryclasses
#混淆时是否做预校验 这里表示不用预先检查
-dontpreverify
#混淆时是否记录日志 添加了表示不用输出详细的过程
-verbose
#表示混淆采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#表示对所有Activity的子类不会进行混淆
-keep public class * extends android.app.Activity
#表示对所有Application 的子类不会进行混淆
-keep public class * extends android.app.Application
#表示对所有Service 的子类不会进行混淆
-keep public class * extends android.app.Service
#表示对所有BroadcastReceiver的子类不会进行混淆
-keep public class * extends android.content.BroadcastReceiver
#表示对所有ContentProvider 的子类不会进行混淆
-keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService
#对support.v4包的申明
-keep class android.support.v4.** { *; }
#表示对所有继承support.v4包里面类的子类不会进行混淆
-keep public class * extends android.support.v4.**
#缺省proguard 会检查每一个引用是否正确,但是第三方库里面往往有些不会用到的类,没有正确引用。如果不配置的话,系统就会报错。
-dontwarn android.support.v4.**
#表示对所有android.app.Fragment 的子类不会进行混淆
-keep public class * extends android.app.Fragment
#表示对所有android.support.v4.widget 的子类不会进行混淆
-keep public class * extends android.support.v4.widget
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
# Gson混淆脚本
-keep class com.google.gson.stream.** {*;}
-keep class com.youyou.uuelectric.renter.Network.user.** {*;}
# ---------------- eventbus避免混淆 ------------
-keepclassmembers class ** {
public void onEvent*(**);
void onEvent*(**);
}
# Glide图片库的混淆处理
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
4.混淆配置完成之后编译混淆包,测试
有的时候混淆之后可能会出现一些奇形怪状的bug,有条件的话,可以让QA回滚一次混淆包的测试。