android 混淆配置 实例实战项目讲解
16lz
2021-01-23
以前一直说混淆、混淆。。。一直没有好好弄一次,经常弄个半成品,这次来个完全实例理解了
并注意,混淆打包后的apk文件大小会比不使用混淆要小。
首先理解下混淆语法
-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
其中app是应用主模块,引用剩余的module,被引用module的build.gradle中都使用默认的设置不启用混淆:
buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
在主module的build.gradle:
apply plugin: 'com.android.application'apply plugin: 'com.neenbedankt.android-apt'def releaseTime() { return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))}repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }}android { compileSdkVersion 25 buildToolsVersion '25.0.0' defaultConfig { applicationId "com.*****.****" //自己的applicationId minSdkVersion 14 targetSdkVersion 25 versionCode 1 versionName "1.0" } //执行lint检查,有任何的错误或者警告提示,都会终止构建,我们可以将其关掉。 lintOptions { abortOnError false } //签名 signingConfigs { debug { } release {// 自己的签名文件 storeFile file("doc/****.jks") storePassword "******" keyAlias "******" keyPassword "******" } } buildTypes { debug { // 显示Log buildConfigField "boolean", "LOG_DEBUG", "true" versionNameSuffix "-debug" minifyEnabled false zipAlignEnabled false shrinkResources false signingConfig signingConfigs.debug } release { // 不显示Log buildConfigField "boolean", "LOG_DEBUG", "false" //混淆 minifyEnabled true //Zipalign优化 zipAlignEnabled true // 移除无用的resource文件 shrinkResources true //前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,后一个文件是自己的定义混淆文件 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //签名 signingConfig signingConfigs.release applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { // 输出apk名称为app_v1.0_2015-xx-xx_xxxx.apk //def fileName = "app_v${defaultConfig.versionName}_${releaseTime()}.apk" def fileName = "app_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk" output.outputFile = new File(outputFile.parent, fileName) } } } } } //渠道Flavors,配置不同风格的app,友盟渠道统计时用到 productFlavors { "offical" {} "360" {} yingyongbao {} wandoujia {} baidu {} "91" {} }}repositories { maven { url "https://repo.eclipse.org/content/repositories/paho-releases/" } maven { url "https://jitpack.io" }}dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:design:23.4.0' compile 'com.android.support:support-v4:23.4.0' compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.android.support:cardview-v7:23.4.0' compile 'com.android.support:recyclerview-v7:23.4.0' //1 achartengine图形 compile files('libs/achartengine-1.1.0.jar') //2 高德地图 compile files('libs/AMap2DMap_2.9.1.jar') //3 butterknife注解 apt 'com.jakewharton:butterknife-compiler:8.1.0' compile 'com.jakewharton:butterknife:8.1.0' //4 smack compile 'org.igniterealtime.smack:smack-android-extensions:4.1.8' compile 'org.igniterealtime.smack:smack-tcp:4.1.8' //5 eventbus compile 'org.greenrobot:eventbus:3.0.0' //6 greendao compile 'org.greenrobot:greendao:3.1.1' //7 FlycoTabLayout_Lib compile 'com.flyco.tablayout:FlycoTabLayout_Lib:[email protected]' //8 mqttv3 compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0' //9 mqtt service compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.0' //10 gson compile 'com.google.code.gson:gson:2.7' //11 MPAndroidChart compile 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1' //12 logger compile 'com.orhanobut:logger:1.15' //13 picasso compile 'com.squareup.picasso:picasso:2.5.2' //14 okhttp3 compile 'com.squareup.okhttp3:okhttp:3.4.1' //15 retrofit2.0 compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.retrofit2:converter-scalars:2.1.0' //16 zxing compile 'com.google.zxing:core:3.3.0'}
proguard-rules.pro文件中则定义了项目的混淆选项,定义如下:
# Add project specific ProGuard rules here.# By default, the flags in this file are appended to flags specified# in D:\COMPETITION\Android Studio\Android Studio SDK/tools/proguard/proguard-android.txt# You can edit the include path and order by changing the proguardFiles# directive in build.gradle.## For more details, see# http://developer.android.com/guide/developing/tools/proguard.html# Add any project specific keep options here:# If your project uses WebView with JS, uncomment the following# and specify the fully qualified class name to the JavaScript interface# class:-keepclassmembers class fqcn.of.javascript.interface.for.webview { public *;}#指定代码的压缩级别-optimizationpasses 5#包明不混合大小写-dontusemixedcaseclassnames#不去忽略非公共的库类-dontskipnonpubliclibraryclasses #优化 不优化输入的类文件-dontoptimize #预校验-dontpreverify #混淆时是否记录日志-verbose # 混淆时所采用的算法-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*#保护注解-keepattributes *Annotation*# 保持哪些类不被混淆-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.app.backup.BackupAgentHelper-keep public class * extends android.preference.Preference-keep public class com.android.vending.licensing.ILicensingService#如果有引用v4包可以添加下面这行-keep public class * extends android.support.v4.app.Fragment#忽略警告-ignorewarning-ignorewarnings##记录生成的日志数据,gradle build时在本项目根目录输出###apk 包内所有 class 的内部结构-dump proguard/class_files.txt#未混淆的类和成员-printseeds proguard/seeds.txt#列出从 apk 中删除的代码-printusage proguard/unused.txt#混淆前后的映射-printmapping proguard/mapping.txt########记录生成的日志数据,gradle build时 在本项目根目录输出-end#######如果引用了v4或者v7包-dontwarn android.support.**####混淆保护自己项目的部分代码以及引用的第三方jar包library-end#####保持 native 方法不被混淆-keepclasseswithmembernames class * { native ;}#保持自定义控件类不被混淆-keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet);}#保持自定义控件类不被混淆-keepclassmembers class * extends android.app.Activity { public void *(android.view.View);}-keep public class * extends android.view.View { public (android.content.Context); public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); public void set*(...);}-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆 public void *(android.view.View);}#保持 Parcelable 不被混淆-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *;}#保持 Serializable 不被混淆-keepnames class * implements java.io.Serializable#保持 Serializable 不被混淆并且enum 类也不被混淆-keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; !static !transient ; !private ; !private ; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve();}#保持枚举 enum 类不被混淆-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String);}-keepclassmembers class * { public void *ButtonClicked(android.view.View);}#不混淆资源类-keepclassmembers class **.R$* { public static ;}#避免混淆泛型 如果混淆报错建议关掉#-keepattributes Signature#移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用,另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制#使用这个配置时,一定要注意 -dontoptimize,配置。#-assumenosideeffects class android.util.Log {# public static *** v(...);# public static *** i(...);# public static *** d(...);# public static *** w(...);# public static *** e(...);#}##################################################################################################################### 以上通用 ###################################################################################################################################################### 常用第三方模块的混淆选项 ####################################1 achartengine-dontwarn org.achartengine.**-keep class org.achartengine.** { *;}#2 高德地图-dontwarn com.amap.api.**#3D 地图-keep class com.amap.api.maps.**{*;} -keep class com.autonavi.amap.mapcore.*{*;} -keep class com.amap.api.trace.**{*;}# 定位-keep class com.amap.api.location.**{*;}-keep class com.amap.api.fence.**{*;}-keep class com.autonavi.aps.amapapi.model.**{*;}# 搜索-keep class com.amap.api.services.**{*;}#2D地图-keep class com.amap.api.maps2d.**{*;}-keep class com.amap.api.mapcore2d.**{*;}# 导航-keep class com.amap.api.navi.**{*;}-keep class com.autonavi.**{*;}#3 butterknife-keep class butterknife.** { *; }-dontwarn butterknife.internal.**-keep class **$$ViewBinder { *; }-keepclasseswithmembernames class * { @butterknife.* ;}-keepclasseswithmembernames class * { @butterknife.* ;}#4 smack-dontwarn org.jivesoftware.**-keep class org.jivesoftware.smack.** { *;}-keep class org.jivesoftware.smackx.** { *;}#5 EventBus3.0-keepattributes *Annotation*-keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe ;}-keep enum org.greenrobot.eventbus.ThreadMode { *; }# Only required if you use AsyncExecutor-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { (Java.lang.Throwable);}#6 GreenDao-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {public static java.lang.String TABLENAME;}-keep class **$Properties# If you do not use SQLCipher:-dontwarn org.greenrobot.greendao.database.**# If you do not use Rx:-dontwarn rx.**#7FlycoTabLayout 可以混淆#8 mqtt 可以混淆#9 mqtt service 可以混淆#10 gson#如果用用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错。-keepattributes Signature# Gson specific classes-keep class sun.misc.Unsafe { *; }# Application classes that will be serialized/deserialized over Gson-keep class com.google.gson.** { *; }-keep class com.google.gson.stream.** { *; }# 如果使用了Gson之类的工具要使被它解析的JavaBean类即实体类不被混淆。-keep class com.app.sample.chatting.api.json.** { *; }-keep class com.app.sample.chatting.bean.** { *; }#11 MPAndroidChart-keep class com.github.mikephil.charting.** { *; }#12 logger可以混淆#13 picasso-keepattributes SourceFile,LineNumberTable-keep class com.parse.*{ *; }-dontwarn com.parse.**-dontwarn com.squareup.picasso.**-keepclasseswithmembernames class * { native <methods>;}#14 okhttp3-dontwarn com.squareup.okhttp3.**-keep class com.squareup.okhttp3.** { *;}-dontwarn okio.**#15 retrofit2-dontwarn retrofit.**-keep class retrofit.** { *; }-keepattributes Signature-keepattributes Exceptions#16 zxing-dontwarn com.google.zxing.**-keep class com.google.zxing.**{*;}#Rxjava Rxandroid-dontwarn sun.misc.**-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { long producerIndex; long consumerIndex;}-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { rx.internal.util.atomic.LinkedQueueNode producerNode;}-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { rx.internal.util.atomic.LinkedQueueNode consumerNode;}
然后执行打包
打包混淆生成后分析选择你的apk文件
可以看到已经混淆了
也可以用反编译工具看看
混淆配置是个细心活,每个工程都不一样,需要根据自己的工程细心配置,否则混淆将会导致工程无法运行