赞
踩
前言:混淆是上线前一个倍儿重要的环节,我们不想自己辛辛苦苦开发的应用被别人反编译出来,并且公司也不允许这样的事情发生。再则,现在面试基本都要求独立开发,不知道怎么混淆是不是很尴尬。那么就让我们看看怎么写混淆文件。当然我使用的是Android studio,还是2.3的。Android Studio自身集成Java语言的ProGuard作为压缩,优化和混淆工具,配合Gradle构建工具使用很简单。后面会有一篇对ProGuard详解的笔记,我们先看一下如何给一个项目加混淆。
一、具体步骤
1.在工程应用目录的gradle文件设置minifyEnable为true android { ... buildTypes { release { minifyEnabled true zipAlignEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } 发布应用的时候应该设置zipAlignEnabled为true,可以让安装包中的资源按4字节对齐,可以减少应用在运行时的内存消耗。像Google Play强制要求开发者上传的应用必须是经过zipAlign的 2.到项目中的proguard-rules.pro文件编写混淆规则 不要问我这个文件在哪,我不会告诉你在项目gradle文件下面。打开你会看到好多注解的东西,建议仔细看看,有对一些指令的解释,我没过四级都能看懂! 这是找到的一个模板,同时也是我在实际项目中使用的,拿走不谢。 #---------------------------------基本指令区---------------------------------- -optimizationpasses 5 -dontskipnonpubliclibraryclassmembers -printmapping proguardMapping.txt -optimizations !code/simplification/cast,!field/*,!class/merging/* -keepattributes *Annotation*,InnerClasses -keepattributes Signature -keepattributes SourceFile,LineNumberTable #---------------------------------默认保留区--------------------------------- -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.view.View -keep public class com.android.vending.licensing.ILicensingService -keep class android.support.** {*;} -keep public class * extends android.view.View{ *** get*(); void set*(***); public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); } -keep class **.R$* { *; } -keepclassmembers class * { void *(**On*Event); } #---------------------------------webview------------------------------------ -keepclassmembers class fqcn.of.javascript.interface.for.Webview { public *; } -keepclassmembers class * extends android.webkit.WebViewClient { public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); public boolean *(android.webkit.WebView, java.lang.String); } -keepclassmembers class * extends android.webkit.WebViewClient { public void *(android.webkit.WebView, jav.lang.String); } #---------------------------------1.实体类--------------------------------- -keep class 你的实体类所在的包.** { *; } 如我的包com.academy.english.listen.bean 我的混淆为 -keep class com.academy.english.listen.bean.** { *; } ---------------------------------2.第三方包------------------------------- #glide -keep public class * implements com.bumptech.glide.module.GlideModule -keep public class * extends com.bumptech.glide.AppGlideModule -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; } #eventBu -keepattributes *Annotation* -keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe <methods>; } -keep enum org.greenrobot.eventbus.ThreadMode { *; } # Only required if you use AsyncExecutor -keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { <init>(java.lang.Throwable); } #litepal -keep class org.litepal.** {*;} -keep class * extends org.litepal.crud.DataSupport { *;} #okhttp -dontwarn okhttp3.** -keep class okhttp3.**{*;} #okio -dontwarn okio.** -keep class okio.**{*;} #okgo -dontwarn com.lzy.okgo.** -keep class com.lzy.okgo.**{*;} #okserver -dontwarn com.lzy.okserver.** -keep class com.lzy.okserver.**{*;} #fastjson -keepattributes Signature -dontwarn com.alibaba.fastjson.** -keep class com.alibaba.fastjson.**{*; } #butterknife -keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; } -keepclasseswithmembernames class * { @butterknife.* <fields>; } -keepclasseswithmembernames class * { @butterknife.* <methods>; } 保留区中在项目中没有用到的可以删掉; 修改自己项目中第三方库混淆。查看build.gradle文件看使用了那种三方库,然后去github或者官网上将混淆粘下来就行。用浏览器搜应该也能搜到。我这里就当是笔记下来了,以后用到直接粘,是不是很机智。
二、基本指令的含义:
-optimizationpasses 5 代码混淆的压缩比例,值在0-7之间
-dontskipnonpubliclibraryclassmembers 指定不去忽略非公共的库的类的成员
-printmapping proguardMapping.txt 生成原类名和混淆后的类名的映射文件
-optimizations !code/simplification/cast,!field/*,!class/merging/* 指定混淆是采用的算法
-keepattributes *Annotation*,InnerClasses 不混淆Annotation和内部类
-keepattributes Signature 不混淆泛型
-keepattributes SourceFile,LineNumberTable 这个本身有解释,抛出异常时保留代码行号
写在最后:
在面试中常碰到的问题,那些不需要混淆,面试官也是有点区分你到底做没做过的意思。其实就是我们的保留区,将保留下来的说出来就OK了 1,jni方法不可混淆,因为这个方法需要和native方法保持一致; -keepclasseswithmembernames class * { # 保持native方法不被混淆 native <methods>; } 2,反射用到的类不混淆(否则反射可能出现问题); 3,AndroidMainfest中的类不混淆,所以四大组件和Application的子类和Framework层下所有的类默认不会进行混淆。自定义的View默认也不会被混淆;所以像网上贴的很多排除自定义View,或四大组件被混淆的规则在Android Studio中是无需加入的; 4,与服务端交互时,使用GSON、fastjson等框架解析服务端数据时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象; 5,使用第三方开源库或者引用其他第三方的SDK包时,如果有特别要求,也需要在混淆文件中加入对应的混淆规则; 6,有用到WebView的JS调用也需要保证写的接口方法不混淆,原因和第一条一样; 7,Parcelable的子类和Creator静态成员变量不混淆,否则会产生Android.os.BadParcelableException异常; -keep class * implements Android.os.Parcelable { # 保持Parcelable不被混淆 public static final Android.os.Parcelable$Creator *; } 8,使用enum类型时需要注意避免以下两个方法混淆,因为enum类的特殊性,以下两个方法会被反射调用,见第二条规则。 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } 还有一点:ProGuard混淆的是Android项目里面的java代码,仅仅是java代码。它是无法混淆资源文件drawable、xml等,所以资源文件也是不会混淆的。想对ProGuard有更深一步了解看下面一篇文章。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。