Android 代码混淆

一、定义

将代码转为一种难以理解和阅读的形式。

二、原因

1、【优化】它能优化java的字节码,使程序运行更快;
2、【压缩】缩减App大小,在混淆过程中它会找出未被使用过的类和类成员并删除他们;
3、【混淆】将代码中的类、函数、变量名随机变成无意义的代号形如:a,b,c...之类的,即使我们的APP即使被反编译,也不容易理解和阅读。

三、AndroidStudio混淆

Android SDK中自带了混淆工具,在SDK -> tools ->proguard。

1、在app下build.gradle中将混淆打开。
android {
    compileSdkVersion 23
    buildToolsVersion "24.0.1"
    defaultConfig {
    }
    buildTypes {
        release {
            minifyEnabled true  //混淆打开
            zipAlignEnabled true  //优化代码
            shrinkResources true  //优化资源        
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
 ....
} 
  • minifyEnabled true :开启混淆,删除一些没有引用到的代码,开启混淆编译会变慢因此debug的时候需要关掉;
  • zipAlignEnabled true:对打包的应用程序进行优化,能优化java字节码,提高运行效率,发布之前一定要设置该项为true;
  • shrinkResources true:删除无用资源,也就是没有被引用的文件(drawable,layout,并不是彻底删除,而是保留文件名,但是没有内容);

shrinkResources要和minifyEnabled搭配使用,如果设置minifyEnabled 为false,shrinkResources设为true会报如下错误:

Removing unused resources requires unused code shrinking to be turned on.

更多使用说明可参考:shrinkResources 的使用

  • proguard-android.txt:AndroidStudio默认自动导入的规则,这个文件位于Android SDK根目录\tools\proguard\proguard-android.txt,这里面是一些比较常规的不能被混淆的代码规则。

  • proguard-rules.pro:对我们自己的项目需要特别定义混淆规则,它位于项目app目录下面(app/ proguard-rules.pro),里面的内容需要我们自己编写。默认情况下会对所有代码,包括第三方包都进行混淆,但有些代码或者第三方包是不能混淆的,这就需要我们手动编写混淆规则来保持不能被混淆的部分。

2、proguard-android.txt说明

下面默认的规则中指示了些需要保持不能别混淆的代码。

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

# 混淆时不使用大小写混合类名
-dontusemixedcaseclassnames
# 不跳过library中的非public的类,混淆第三方jar
-dontskipnonpubliclibraryclasses
# 打印混淆的详细信息
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
# 关闭优化(原因见上边的原英文注释)
-dontoptimize
# 不进行预校验,可加快混淆速度
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

# 保留注解中的参数
-keepattributes *Annotation*
# 不混淆如下两个谷歌服务类
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
# 不混淆包含native方法的类的类名以及native方法名
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
# 不混淆View中的setXxx()和getXxx()方法,以保证属性动画正常工作
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
# 不混淆Activity中参数是View的方法,例如,一个控件通过android:onClick="clickMethodName"绑定点击事件,混淆后会导致点击事件失效
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
# 不混淆枚举类中的values()和valueOf()方法
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 不混淆Parcelable实现类中的CREATOR字段,以保证Parcelable机制正常工作
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

# 不混淆R文件中的所有静态字段,以保证正确找到每个资源的id
-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
# 不对android.support包下的代码警告(如果我们打包的版本低于support包下某些类的使用版本,会出现警告的问题)
-dontwarn android.support.**

# Understand the @Keep support annotation.
# 不混淆Keep类
-keep class android.support.annotation.Keep

# 不混淆使用了注解的类及类成员
-keep @android.support.annotation.Keep class * {*;}

# 如果类中有使用了注解的方法,则不混淆类和类成员
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

# 如果类中有使用了注解的字段,则不混淆类和类成员
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

# 如果类中有使用了注解的构造函数,则不混淆类和类成员
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}
3、混淆配置的语法

如果你能把上面proguard-android.txt说明看完,基本就可以照着写出自己的混淆文件,如果需要了解更多可参考文章:ProGuard 最全混淆规则说明

4、不能混淆代码说明
  • 四大组件和Application:Activity、service等和Application不能混淆。现在的系统已经配置为混淆时候会保留Android系统组件;

  • 使用反射的类:因为代码混淆,类名、方法名、属性名都改变了,而反射它还是按照原来的名字去反射,结果程序崩溃。

  • 注解:因为注解也用到了java反射,所以不能混淆。

  • 自定义View:因为被Android Resource 文件引用到的,名字已经固定,也不能混淆。自定义view是带了包名写在xml布局中的。

  • JavaBean 类:使用了 Gson 之类的工具要使 JavaBean 类即实体类不能混淆。因为json转换用到了java反射。

  • 泛型:泛型不能混淆。

  • 自定义控件类:控件类的get/set方法和构造函数不能混淆。

  • 内部类:如果内部类会被外部调用到,那么也不能混淆。

  • 使用了枚举的类:使用了枚举要保证枚举不被混淆。

  • 第三方库类:对第三方库中的类不进行混淆。

  • 包含native方法类:不混淆任何包含native方法的,否则找不到本地方法。

  • 属性动画兼容库:属性动画兼容库不能混淆。

  • 在引用第三方库的时候,一般会标明库的混淆规则的,建议在使用的时候就把混淆规则添加上去,免得到最后才去找。

  • 不混淆Rxjava/RxAndroid。

  • 数据库驱动。

5、混淆后调试

在Android studio 中生成release包的同时 build\outputs\mapping\release文件夹下也生成了4个文件:

  • configuration.txt :总的混淆规则。这个文件包含了打包过程中所有混淆规则的汇总。

  • mapping.txt :列出了原始的类,方法,和字段名与混淆后代码之间的映射。

  • seeds.txt :列出了未被混淆的类和成员。

  • usage.txt : 列出了从apk中删除的代码。

根据上面文件信息,反推出原代码逻辑问题。

使用retrace工具
该工具在sdk根目录\tools\proguard\bin\retrace.sh,使用步骤:

  • 保存crash日志,转存到bug.txt中;

  • 删掉Crash日志中AndroidRuntime前面的信息;

  • 打开命令窗口执行命令:如: ./retrace.sh mapping.txt bug.txt

参考文章:
Android 代码混淆零基础入门
Android 混淆代码,优化

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • 本篇文章:自己在混淆的时候整理出比较全面的混淆方法,比较实用,自己走过的坑,淌出来的路。请大家不要再走回头路,可能...
    Zane_Samuel阅读 55,271评论 8 93
  • 一、混淆基本原理及目的: 目的:让反编译app后的代码很难看懂,只是让别人很难看的懂而已。 基本原理:把代码中原来...
    夜沐下的星雨阅读 1,311评论 0 3
  • 前言 代码混淆对于每个入门的 Android 工程师来说都不会太陌生,因为在编译正式版本时,这是一个必不可少的过程...
    彭旭锐阅读 5,050评论 2 45
  • 一、概述 ProGuard 会检测和移除封装应用中未使用的类、字段、方法和属性,包括自带代码库中的未使用项(这使其...
    编码前线阅读 867评论 0 3
  • 1、前言 在对apk进行打包时,如果不对apk进行混淆和加固,生成的apk可以轻松的进行反编译,所以对apk代码进...
    杰奎琳子阅读 1,318评论 0 12