不论是商用APK还是个人开发的APK,一旦放在网络上,都将面临一个问题:开发者辛辛苦苦开发的程序被他人反编译,轻松获取开发者的源代码。如果对方仅仅只是拿来学习,或许开发者会很乐意这样;但是如果对方拿来危害开发者或者企业利益,甚至危害社会利益,那就是开发者所不愿意看到的了。
为了防止开发者代码被轻易窃取,代码混淆概念的引入也就应运而生了。百度百科上给 代码混淆 的定义如下:
代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码,也可以用于程序编译而成的中间代码。执行代码混淆的程序被称作代码混淆器。目前已经存在许多种功能各异的代码混淆器。
Google似乎也发现了反编译的问题,从SDK2.3开始我们可以看到在android-sdk-windows\tools\下面多了一个proguard文件夹。
ProGuard是一个免费的Java类文件收缩,优化,混淆和预校验器。它可以检测并删除未使用的类,字段,方法和属性。它可以优化字节码,并删除未使用的指令。它可以将类、字段和方法使用短无意义的名称进行重命名。最后,预校验的Java6或针对Java MicroEdition的所述处理后的码。
**一、混淆的规则
**
ProGuard默认会对第三方库也进行混淆的,而第三方库有的已经混淆过了,有的使用了Java反射技术,
所以我们在进行代码混淆的时候要排除这些第三方库。排除对第三方库的混淆需要在混淆规则文件(通
常是:proguard-project.txt或proguard.cfg或proguard-rules.pro或proguard-rules.txt也可以是其
它的文件名只要在配置文件中将含有混淆规则的文件名配置进去就行了)中添加如下规则:
1.如果使用了Gson之类的工具要使JavaBean类即实体类不被混淆。
2.如果使用了自定义控件那么要保证它们不参与混淆。
3.如果使用了枚举要保证枚举不被混淆。
4.对第三方库中的类不进行混淆
a.混淆时保护引用的第三方jar包
如:-libraryjars libs/baidumapapi_v3_2_0.jar #保护引用的第三方jar包不被混淆
注意:在使用Eclipse+ADT时需要加入-libraryjars libs/...,如果你是使用Android Studio开发的项目则不需要加入libs包中的jar包,这是因为,通过Android Studio进行混淆代码时,默认已经将 lib目录中的 jar 都已经添加到打包脚本中,所以不需要再次手动添加,否则会出现“ java.io.IOException: The same input jar is specified twice” 错误。
b.混淆时保护第三方jar包中的类不被混淆
如:-keep class com.baidu.** { ; } #让ProGuard不要警告找不到com.baidu.这个包里面的类的相关引用
-dontwarn com.baidu.* #保持com.baidu.**这个包里面的所有类和所有方法不被混淆。
**二、开发工具为eclispe+sdk和开发工具为Android Studio两种方式的介绍混淆。
**
1、开发工具为eclispe+sdk的混淆介绍
下面具体说一说怎么样让SDK2.3下的proguard.cfg文件起作用,先来看看android-sdk-windows\tools\lib*proguard.cfg*的内容:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-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 com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(;
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
从脚本中可以看到,混淆中保留了继承自Activity、Service、Application、BroadcastReceiver、ContentProvider等基本组件以及com.android.vending.licensing.ILicensingService,
并保留了所有的Native变量名及类名,所有类中部分以设定了固定参数格式的构造函数,枚举等等。(详细信息请参考/examples中的例子及注释。)
让proguard.cfg起作用的做法很简单,就是在eclipse自动生成的default.properties文件中加上一句“proguard.config=proguard.cfg”就可以了
完整的default.properties文件应该如下:
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-9
proguard.config=proguard.cfg
大功告成,正常的编译签名后就可以防止代码被反编译了。反编译经过代码混淆的apk得到的代码应该类似于下面的效果,是很难看懂的:
如果您使用的是2.3之前的SDK版本也没关系,把上面的proguard.cfg文件复制一份放到项目中,然后进行相同的操作即可。
2、开发工具为****Android Studio****的混淆介绍
使用Android Studio工具中,将混淆文件的存放路径为:项目所在文件夹路径\app\proguard-rules.pro,其中proguard-rules.pro名字是由gradle配置文件指定的,接下来介绍gradle配置文件中设置混淆。
在gradle下的配置文件信息为:
buildTypes {
release {
signingConfig signingConfigs.release //设置签名信息
minifyEnabled false //true表示开启混淆,false表示关闭混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆规则文件名
}
debug {
signingConfig signingConfigs.debug
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
只要在文件proguard-rules.pro中设置符合混淆规则,就可以轻松的完成混淆,是不是很简单呢?
我列举下我用过或者见过的混淆设置给大家借鉴,希望对各位有帮助:
字节跳动内推码
字节跳动内推码