Android 代碼混淆

一、定義

將代碼轉(zhuǎn)為一種難以理解和閱讀的形式。

二、原因

1、【優(yōu)化】它能優(yōu)化java的字節(jié)碼,使程序運行更快;
2、【壓縮】縮減App大小,在混淆過程中它會找出未被使用過的類和類成員并刪除他們;
3、【混淆】將代碼中的類、函數(shù)、變量名隨機變成無意義的代號形如: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  //優(yōu)化代碼
            shrinkResources true  //優(yōu)化資源        
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
 ....
} 
  • minifyEnabled true :開啟混淆,刪除一些沒有引用到的代碼,開啟混淆編譯會變慢因此debug的時候需要關掉;
  • zipAlignEnabled true:對打包的應用程序進行優(yōu)化,能優(yōu)化java字節(jié)碼,提高運行效率,發(fā)布之前一定要設置該項為true;
  • shrinkResources true:刪除無用資源,也就是沒有被引用的文件(drawable,layout,并不是徹底刪除,而是保留文件名,但是沒有內(nèi)容);

shrinkResources要和minifyEnabled搭配使用,如果設置minifyEnabled 為false,shrinkResources設為true會報如下錯誤:

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

更多使用說明可參考:shrinkResources 的使用

  • proguard-android.txt:AndroidStudio默認自動導入的規(guī)則,這個文件位于Android SDK根目錄\tools\proguard\proguard-android.txt,這里面是一些比較常規(guī)的不能被混淆的代碼規(guī)則。

  • proguard-rules.pro:對我們自己的項目需要特別定義混淆規(guī)則,它位于項目app目錄下面(app/ proguard-rules.pro),里面的內(nèi)容需要我們自己編寫。默認情況下會對所有代碼,包括第三方包都進行混淆,但有些代碼或者第三方包是不能混淆的,這就需要我們手動編寫混淆規(guī)則來保持不能被混淆的部分。

2、proguard-android.txt說明

下面默認的規(guī)則中指示了些需要保持不能別混淆的代碼。

# 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).
# 關閉優(yōu)化(原因見上邊的原英文注釋)
-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.

# 保留注解中的參數(shù)
-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中參數(shù)是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實現(xiàn)類中的CREATOR字段,以保證Parcelable機制正常工作
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

# 不混淆R文件中的所有靜態(tài)字段,以保證正確找到每個資源的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包下某些類的使用版本,會出現(xiàn)警告的問題)
-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>;
}

# 如果類中有使用了注解的構造函數(shù),則不混淆類和類成員
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}
3、混淆配置的語法

如果你能把上面proguard-android.txt說明看完,基本就可以照著寫出自己的混淆文件,如果需要了解更多可參考文章:ProGuard 最全混淆規(guī)則說明。

4、不能混淆代碼說明
  • 四大組件和Application:Activity、service等和Application不能混淆?,F(xiàn)在的系統(tǒng)已經(jīng)配置為混淆時候會保留Android系統(tǒng)組件;

  • 使用反射的類:因為代碼混淆,類名、方法名、屬性名都改變了,而反射它還是按照原來的名字去反射,結果程序崩潰。

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

  • 自定義View:因為被Android Resource 文件引用到的,名字已經(jīng)固定,也不能混淆。自定義view是帶了包名寫在xml布局中的。

  • JavaBean 類:使用了 Gson 之類的工具要使 JavaBean 類即實體類不能混淆。因為json轉(zhuǎn)換用到了java反射。

  • 泛型:泛型不能混淆。

  • 自定義控件類:控件類的get/set方法和構造函數(shù)不能混淆。

  • 內(nèi)部類:如果內(nèi)部類會被外部調(diào)用到,那么也不能混淆。

  • 使用了枚舉的類:使用了枚舉要保證枚舉不被混淆。

  • 第三方庫類:對第三方庫中的類不進行混淆。

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

  • 屬性動畫兼容庫:屬性動畫兼容庫不能混淆。

  • 在引用第三方庫的時候,一般會標明庫的混淆規(guī)則的,建議在使用的時候就把混淆規(guī)則添加上去,免得到最后才去找。

  • 不混淆Rxjava/RxAndroid。

  • 數(shù)據(jù)庫驅(qū)動。

5、混淆后調(diào)試

在Android studio 中生成release包的同時 build\outputs\mapping\release文件夾下也生成了4個文件:

  • configuration.txt :總的混淆規(guī)則。這個文件包含了打包過程中所有混淆規(guī)則的匯總。

  • mapping.txt :列出了原始的類,方法,和字段名與混淆后代碼之間的映射。

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

  • usage.txt : 列出了從apk中刪除的代碼。

根據(jù)上面文件信息,反推出原代碼邏輯問題。

使用retrace工具
該工具在sdk根目錄\tools\proguard\bin\retrace.sh,使用步驟:

  • 保存crash日志,轉(zhuǎn)存到bug.txt中;

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

  • 打開命令窗口執(zhí)行命令:如: ./retrace.sh mapping.txt bug.txt

參考文章:
Android 代碼混淆零基礎入門
Android 混淆代碼,優(yōu)化

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 本篇文章:自己在混淆的時候整理出比較全面的混淆方法,比較實用,自己走過的坑,淌出來的路。請大家不要再走回頭路,可能...
    Zane_Samuel閱讀 55,619評論 8 93
  • 一、混淆基本原理及目的: 目的:讓反編譯app后的代碼很難看懂,只是讓別人很難看的懂而已。 基本原理:把代碼中原來...
    夜沐下的星雨閱讀 1,688評論 0 3
  • 前言 代碼混淆對于每個入門的 Android 工程師來說都不會太陌生,因為在編譯正式版本時,這是一個必不可少的過程...
    彭旭銳閱讀 5,518評論 2 44
  • 一、概述 ProGuard 會檢測和移除封裝應用中未使用的類、字段、方法和屬性,包括自帶代碼庫中的未使用項(這使其...
    編碼前線閱讀 986評論 0 3
  • 1、前言 在對apk進行打包時,如果不對apk進行混淆和加固,生成的apk可以輕松的進行反編譯,所以對apk代碼進...
    杰奎琳子閱讀 1,504評論 0 12

友情鏈接更多精彩內(nèi)容