關於Android studio混淆

一、概述

這幾天要打包APK給測試,但是一打包發現APK包有23M,經理那邊自然過不了,所以就開始琢磨怎麼減小APK的大小。分析原因:

1. 由於UI是按照模塊給的切圖,所以部分模塊的切圖可能存在重複,不過這種情況不多,所以對apk的大小影響不大。如果想通過減少圖片來減小apk的大小,那麼建議只做一套切圖,單獨適應xhdpi的。

2. 如果不需要做國際化,建議指定只支持中文的

                defaultConfig {  
                    resConfigs "zh"  
                }

3. 我們的app中部分用到了h5,而h5的代碼是存放到assets目錄下,這個目錄下的文件打包的時候是不會被壓縮的,所以這個目錄下的文件有多大,打包之後apk就會增加多大。目前關於h5的資源代碼等還不知道怎麼壓縮處理,各位大神有什麼好的方法請教一下。

4. 這個就是重點了,android studio默認build.gradle裏面配置的 minifyEnable false,這表示是不混淆,起不到防反編譯的作用。


二、配置 build.gradle 文件

1. 修改配置:

buildTypes {
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    debug{
        minifyEnabled false
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
其中release{}指的是發佈版本,也就是通過android studio工具欄中Build生成的apk;debug{}指的是調試版本,也就是通過adb連接設備直接運行生成的apk。minifyEnabled表示是否啓動代碼混淆,shrinkResources表示是否刪除代碼中無用的resource文件。

注意:想要讓 shrinkResources true 生效,就必須設置 minityEnabled true。否則就算shrinkResources true,而minifyEnabled fale,那麼還是不會起到作用。

proguardFiles指定的是混淆的配置文件。


三、修改混淆配置文件 proguard-rules.pro

-optimizationpasses 5          # 指定代碼的壓縮級別0-7
-dontusemixedcaseclassnames   # 是否使用大小寫混合
-dontpreverify           # 混淆時是否做預校驗
-verbose                # 混淆時是否記錄日誌

-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*  # 混淆時所採用的算法

# 保持 AndroidManifext.xml 文件裏面註冊的組件不被混淆
-keep public class * extends android.app.Fragment
-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
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**

#註解不被混淆
-keepattributes *Annotation*
#泛型不被混淆
 -keepattributes Signature#如果引用了v4或者v7-dontwarn android.support.**-keep class android.support.v4.**{*;}#保持 native 方法不被混淆(jni)-keepclasseswithmembernames class * { native <methods>;}#保持 Parcelable 不被混淆-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *;}#保持 Serializable 不被混淆-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

 -keepclassmembers class * { public void *ButtonClicked(android.view.View);}#不混淆資源類-keepclassmembers class **.R$* { public static <fields>;}

# 保持枚舉 enum 類不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

 # 保持自定義控件類不被混淆-keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet);}#保持自定義控件類不被混淆-keepclassmembers class * extends android.app.Activity { public void *(android.view.View);}-keep public class * extends android.view.View { public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); public void set*(...);}

一般我們的項目中都會用到第三方的框架,這個也是要配置,否則會報各種異常,通常情況下,瞎子第三方jar的時候都有教怎麼配置的,例如:

Gson的配置:

#-------------- Gson------------------------
-keep class com.google.gson.stream.** { *; }
-keepattributes EnclosingMethod #反射不混淆
#這是你定義的實體類(gson解析會通過反射的方式得到bean類)
-keep class 包名.**{*;}
okhttputils的配置:

#okhttp
-dontwarn okhttp3.**
-keep class okhttp3.**{*;}
#okio
-dontwarn okio.**
-keep class okio.**{*;}

對於webview的混淆問題:

#解決webviewjs的交互問題(#後面的內部,JSLoadNative是js調用android的接口)
-keepclassmembers class 包名.BaseActivity$JSLoadNative {
    public *;
}
-keepattributes JavascriptInterface

四、總結

1. Android 混淆原則:
             反射用到的類不混淆
            JNI方法不混淆
            AndroidMainfest中的類不混淆,四大組件和Application的子類和Framework層下所有的類默認不會進行混淆
            Parcelable的子類和Creator靜態成員變量不混淆,否則會產生android.os.BadParcelableException異常
            使用GSON、fastjson等框架時,所寫的JSON對象類不混淆,否則無法將JSON解析成對應的對象
            使用第三方開源庫或者引用其他第三方的SDK包時,需要在混淆文件中加入對應的混淆規則
            有用到WEBView的JS調用也需要保證寫的接口方法不混淆

2. 混淆小技巧:

            對於第三方的jar包直接照着提供的修改
            對於有的類找不到,就直接-keep掉,然後再運行修改
           build.gradle文件默認不會配置debug模式,自己添加配置debug模式,這樣就可以直接通過adb來調試混淆引起的一些問題了

3. 注意:

           eclipse裏面是需要 -libraryjars 來導入我們使用到的jar的,但是studio裏面就不需要,相反,如果你再次引用打包的時候就會報引用了兩次的錯誤。



這樣改了之後,再次打包發現apk比之前小了6M多。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章