Android ProGuard代码混淆

转:http://blog.csdn.net/hanhailong726188/article/details/50421991
简介

Proguard工具通过移除无用的代码以及使用语义隐晦的名称来重命名类、字段和方法,从而达到压缩、优化和混淆代码的目的。最终您将获得一个较小的 .apk 文件,此文件更难于进行反向工程。由于 ProGuard 会使应用更难于进行反向工程,因此当应用使用对安全性要求极高的功能时(例如,当您向应用授予许可时),您必须使用此工具。

ProGuard 已集成到 Android 构建系统,所以您无需手动调用此工具。只有当您在发布模式下构建应用时,ProGuard 才会运行,因此当您在调试模式下构建应用时,就无需处理混淆后的代码。是否运行 ProGuard 完全由您决定,但我们强烈建议您运行该工具。

本文介绍如何启用和配置 ProGuard,以及如何使用 retrace 工具解码混淆后的堆栈跟踪信息。

开启Proguard

Ant、Eclipse构建

/project.properties 文件中设置 proguard.config 属性。该路径可以是绝对路径,也可以是项目根目录的相对路径。

proguard.config=proguard.cfg
AndroidStudio-Gradle构建

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }
    }

    productFlavors {
        flavor1 {
        }
        flavor2 {
            proguardFile 'some-other-rules.txt'
        }
    }
}

提示:

getDefaultProguardFile()可以返回这两个文件的绝对路径。
proguardFile 可以配置多个混淆文件

配置Proguard

在某些情况下,proguard.cfg或proguard-android.txt 文件中的默认配置足以满足您的需求。不过,在很多情况下,ProGuard 很难做出正确分析,因此可能会移除它认为无用而实际上您的应用却需要的代码。部分示例如下:

一个只在 AndroidManifest.xml 文件中引用的类
一个通过 JNI 调用的方法
动态引用的字段和方法
默认的 proguard.cfg或proguard-android.txt 文件旨在涵盖一般的使用情形,但您可能会遇到异常情况,例如 ClassNotFoundException(此异常情况会在 ProGuard 删除您的应用调用的整个类时发生)。

您可以通过在 proguard.cfg或proguard-android.txt 文件中添加一个 -keep 行,来修复因 ProGuard 在删除代码而造成的错误。例如:

-keep public class
在使用 -keep 选项时,您既有许多选择也有不少需要注意的方面,因此我们强烈建议您阅读 ProGuard 手册,详细了解如何自定义您的配置文件。该手册中的“Keep 选项概述”和“示例”部分尤其有用;问题排查部分则概述了在 ProGuard 删除代码后您可能会遇到的其他常见问题。

下面给出一个常用的默认配置命令:

-include {fileame}  从给定的文件中读取配置参数
-libraryjars libs/xxxx.jar 指定库jar包
-keep public class * extends android.app.Activity 保留类不被删除
-keep class className$InnerName{ 保留内部类的属性和方法
    public ;
    public ;
}
-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();
}
-dontshrink 不压缩输入的类文件
-dontoptimize 不优化输入的类文件
-keepattributes *Annotation* 保留Annotation
-dontwarn xxx.xxx.** 不检查引用
Proguard产生的文件

当混淆后的代码输出堆栈跟踪信息时,方法名称会被混淆,即便仍能进行调试,难度也会很大。幸运的是,ProGuard 在每次运行时都会输出以下文件:

dump.txt

描述 .apk 文件中所有类文件的内部结构

mapping.txt

列出原始与混淆后的类、方法和字段名称之间的对应关系。

Windows 上的 retrace.bat 脚本以及 Linux 或 Mac OS X 上的 retrace.sh 脚本可以将混淆后的堆栈跟踪信息转换成可读文件,此文件位于 /tools/proguard/ 目录中。执行 retrace 工具的语法如下:

retrace.bat|retrace.sh [-verbose] mapping.txt []
例如:

retrace.bat -verbose mapping.txt obfuscated_trace.txt
建议发布时应保留mapping.txt文件。

seeds.txt

列出未混淆的类和成员

usage.txt

列出从 .apk 删除的代码

@Keep注解来防止混淆

写到这,你是不是发现了一个问题:非常的麻烦、一点都不灵活,而且通过-keep的方式防止混淆那种有共同特征的类、属性或方式非常有用,但是没有共同特征的呢?

这里介绍一种比较新颖、轻快的方法,通过@Keep注解来灵活的防止混淆,用起来非常的灵活、快捷、方便,怎样用呢?像普通的注解一样,如下:

//防止混淆类
@Keep
public class Person {}

//防止混淆变量
@Keep
public String name;

//防止混淆方法
@Keep
public int getAge(){}
但是当你加上上面的注解后,发现@Keep并没有起作用,该混淆的还是混淆了,这是为什么呢?

原因目前Gradle还不支持@Keep混淆,Google只是定义好了一个这种注解,并没有实现它,也就是说@Keep目前只是一个空壳。这里我们来手动开启它,让它支持防止混淆,在你的proguard.cfg或proguard-android.txt配置文件里面加入以下代码:

手动启用support keep注解

-dontskipnonpubliclibraryclassmembers
-printconfiguration
-keep,allowobfuscation @interface android.support.annotation.Keep
-keep @android.support.annotation.Keep class *
-keepclassmembers class * {
@android.support.annotation.Keep *;
}

你可能感兴趣的:(Android,android)