前言:
随着现在开发者越来越谱遍,各种各样的应用随之诞生,所以项目混淆是很有必要的。混淆可以减小包的大小,还可以防止反编译(产品),当然我们要有分享的精神,对一些干货就没有必要混淆。但是如果是公司的项目还是有必要进行混淆的。在此之前我很感谢两个人:一个是我在平安科技的老大(东哥),再者是我的好朋友前北京LeTv(乐视)现SenseTime大神给予我的帮助及讲解。当然网络也有更种样式的混淆博客,看得越多就会始终觉得太乱。为了项目更好的总结Android的混淆,故此将自己的混淆过程比较详细的分享下,方便有需要的人,攒点人品。注:这里主要讲Android Studio.
一、理论知识
ProGuard 是一款免费的Java类文件压缩器、优化器和混淆器。它能发现并删除无用类、字段(field)、方法和属性值(attribute)。它也能优化字节码 并删除无用的指令。最后,它使用简单无意义的名字来重命名你的类名、字段名和方法名。经过以上操作的jar文件会变得更小,并很难进行逆向工程。
二、基本使用
ProGuard来进行混洗打包,大大的优化Apk包的大小。但是注意ProGuard对文件路径的名名很有讲究,不支持括号,也不支持空格。在混淆过后,可以在工程目录的proguard中的mapping.txt看到混淆后的类名,方法名,变量名和混淆前的类名,方法名,变量名。
废话不多说...
1.我们在新建项目的时候会自动生存一个混淆文件(proguard-rules.pro)
2.配制build.gradle文件
以上是基本工作,只要完成上面两步就可以了。 接下来就是写混淆文件,我会把一些常用的签写上注释方便阅读。
编写proguard-rules.pro混淆文件
#############################################
#
# 对于一些基本指令的添加
#
#############################################
# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
-optimizationpasses5
# 去除编译时警告
-ignorewarnings
#不压缩输入的类文件
-dontshrink
#不优化输入的类文件
-dontoptimize
# 不混淆输入的类文件
#-dontobfuscate
# 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames
# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
# 这句话能够使我们的项目混淆后产生映射文件
# 包含有类名->混淆后类名的映射关系
-verbose
# 指定不去忽略非公共库的类成员
-dontskipnonpubliclibraryclassmembers
# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
-dontpreverify
# 保留Annotation不混淆x
-keepattributes*Annotation*,InnerClasses
-keepclass * extends java.lang.annotation.Annotation {*;}
# 避免混淆泛型
-keepattributesSignature
# 抛出异常时保留代码行号
-keepattributesSourceFile,LineNumberTable
# 指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations!code/simplification/cast,!field/*,!class/merging/*
#记录生成的日志数据,gradle build时在本项目根目录输出
#apk 包内所有 class 的内部结构
-dumpclass_files.txt
#未混淆的类和成员
-printseedsseeds.txt
#列出从 apk 中删除的代码
-printusageunused.txt
#混淆前后的映射
-printmappingmapping.txt
##############################################
#
# Android开发中一些需要保留的公共部分
#
#############################################
# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆
# 因为这些子类都有可能被外部调用
-keeppublic class * extends android.app.Activity
-keeppublic class * extends android.app.Appliction
-keeppublic class * extends android.app.Service
-keeppublic class * extends android.content.BroadcastReceiver
-keeppublic class * extends android.content.ContentProvider
-keeppublic class * extends android.app.backup.BackupAgentHelper
-keeppublic class * extends android.preference.Preference
-keeppublic class * extends android.view.View
-keeppublic class com.android.vending.licensing.ILicensingService
# 保留support下的所有类及其内部类
-keepclass android.support.** {*;}
# 保留继承的
-keeppublic class * extends android.support.v4.**
-keeppublic class * extends android.support.v7.**
-keeppublic class * extends android.support.annotation.**
# 保留R下面的资源
-keepclass **.R$* {*;}
# 保留本地native方法不被混淆
-keepclasseswithmembernamesclass * {
native ;
}
# 保留在Activity中的方法参数是view的方法,
# 这样以来我们在layout中写的onClick就不会被影响
-keepclassmembersclass * extends android.app.Activity{
public void *(android.view.View);
}
# 保留枚举类不被混淆
-keepclassmembersenum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# 保留我们自定义控件(继承自View)不被混淆
-keeppublic class * extends android.view.View{
*** get*();
void set*(***);
public (android.content.Context);
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
}
# 保留Parcelable序列化类不被混淆
-keepclass * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# 保留Serializable序列化的类不被混淆
-keepclassmembersclass * 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();
}
# 对R文件下的所有类及其方法,都不能被混淆
-keepclassmembersclass **.R$* {
*;
}
# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembersclass * {
void *(**On*Event);
void *(**On*Listener);
}
# webView处理,项目中没有使用到webView忽略即可
-keepclassmembersclass fqcn.of.javascript.interface.for.webview {
public *;
}
-keepclassmembersclass * extends android.webkit.webViewClient {
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
public boolean *(android.webkit.WebView, java.lang.String);
}
-keepclassmembersclass * extends android.webkit.webViewClient {
public void *(android.webkit.webView, jav.lang.String);
}
#================以下是第三方的=============
# 百度地图(jar包换成自己的版本,记得签名要匹配)
-keepclass com.baidu.** {*;}
-keepclass vi.com.** {*;}
-keepclass com.sinovoice.** {*;}
-keepclass pvi.com.** {*;}
-dontwarncom.baidu.**
-dontwarnvi.com.**
-dontwarnpvi.com.**
# Gson
-keepattributesSignature -keepattributes *Annotation*
-keepclass sun.misc.Unsafe {*;}
-keepclass com.google.gson.stream.** {*;}
# 使用Gson时需要配置Gson的解析对象及变量都不混淆。不然Gson会找不到变量。
# 将下面替换成自己的实体类
-keepclass com.bayekeji.dizhu.Models.** {*;}
# Realm
-keepclass io.realm.annotations.RealmModule
-keep@io.realm.annotations.RealmModule class *
-keepclass io.realm.internal.Keep
-keep@io.realm.internal.Keep class * {*;}
-dontwarnjavax.**
-dontwarnio.realm.**
# 微信支付
-dontwarncom.tencent.mm.**
-dontwarncom.tencent.wxop.stat.**
-keepclass com.tencent.mm.** {*;}
-keepclass com.tencent.wxop.stat.**{*;}
# 支付宝钱包
-dontwarncom.alipay.**
-dontwarnHttpUtils.HttpFetcher
-dontwarncom.ta.utdid2.**
-dontwarncom.ut.device.**
-keepclass com.alipay.android.app.IAlixPay{*;}
-keepclass com.alipay.android.app.IAlixPay$Stub{*;}
-keepclass com.alipay.android.app.IRemoteServiceCallback{*;}
-keepclass com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keepclass com.alipay.sdk.app.PayTask{public *;}
-keepclass com.alipay.sdk.app.AuthTask{public *;}
-keepclass com.alipay.mobilesecuritysdk.*
-keepclass com.ut.*
#------umeng 相关的混淆配置-----------
-keepclass com.umeng.** {*;}
-keepclass com.umeng.analytics.** {*;}
-keepclass com.umeng.common.** {*;}
-keepclass com.umeng.newxp.** {*;}
#不混淆招行jar包
-keepclass cmb.pb.** {*;}
总结:
以上是我在项目中常用的一些混淆配制,基本上可以放在自己的项目中用,相信大家对Android 混淆有了详细的了解。如果有更好的更详细的混淆文件配制,欢迎留言。