Android:混淆文件proguard.cfg詳解

在android項目中,一般都要使用代碼混淆,在項目的根目錄下,
這裏寫圖片描述
紅色圈中部分是代碼混淆的文件。
下面給出proguard.cfg文件的內容:

#指定代碼的壓縮級別
-optimizationpasses 5
 #混淆時不會產生形形色色的類名  是否使用大小寫混合
-dontusemixedcaseclassnames
 #指定不去忽略非公共的類庫 是否混淆第三方jar
-dontskipnonpubliclibraryclasses
#不預校驗  混淆時是否做預校驗
-dontpreverify
#混淆時是否記錄日誌
-verbose 
-ignorewarnings
#優化 混淆時所採用的算法
-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 com.android.vending.licensing.ILicensingService
#保護指定的類和類的成員的名稱,如果所有指定的類成員出席(在壓縮步驟之後)
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}
#保護指定的類和類的成員,但條件是所有指定的類和類成員是要存在。
#保持自定義控件類不被混淆
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {  
    public <init>(android.content.Context);  
}
#保護指定類的成員,如果此類受到保護他們會保護的更好 
-keepclassmembers class * extends android.app.Activity { 
public void *(android.view.View); 
}
#保持枚舉 enum 類不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#保護指定的類文件和類的成員
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** i(...);
}
-keepclassmembers class **.R$* {
    public static <fields>;
}
#引用的庫的jar,添加進來
-libraryjars libs/android-support-v4.jar
-libraryjars libs/android-viewbadger.jar
-libraryjars libs/baidumapapi_v3_2_0.jar
-libraryjars libs/cyberplayer-sdk.jar
-libraryjars libs/jpush-sdk-release1.7.2.jar
-libraryjars libs/ksoap2-android.jar
-libraryjars libs/locSDK_3.3.jar
-libraryjars libs/universal-image-loader-1.9.4-with-sources.jar
-libraryjars libs/picasso-2.4.0.jar
-libraryjars libs/umeng-analytics-v5.2.4.jar
-libraryjars libs/HMSDK.jar
-libraryjars libs/KJFrameForAndroid_v2.245.jar

-dontwarn com.huamaitel.**
-keep class com.huamaitel.** { *;}

-dontwarn javax.security.sasl.**
-keep class javax.security.sasl.** { *;}

-dontwarn android.support.v4.**
-keep class android.support.v4.** { *;}

-dontwarn com.baidu.**
-keep class com.baidu.** { *;}

-dontwarn cn.jpush.**
-keep class cn.jpush.** { *;}

-dontwarn com.umeng.**
-keep class com.umeng.** { *;}
-dontwarn u.aly.**
-keep class u.aly.** { *;}

-dontwarn com.squareup.**
-keep class com.squareup.** { *;}

-dontwarn org.ksoap2.**
-keep class org.ksoap2.** { *;}
-dontwarn org.kobjects.**
-keep class org.kobjects.** { *;}
-dontwarn org.kxml2.**
-keep class org.kxml2.** { *;}
-dontwarn org.xmlpull.**
-keep class org.xmlpull.** { *;}

-dontwarn com.nostra13.universalimageloader.**
-keep class com.nostra13.universalimageloader.** { *;}

-keep class vi.com.gdi.bgl.** {*;}

-dontwarn com.readystatesoftware.**
-keep class com.readystatesoftware.** { *;}

-dontwarn org.kymjs.**
-keep class org.kymjs.** {*;}

#下面幾行 是環信即時通信的代碼混淆
-keep class com.easemob.** {*;}
-keep class org.jivesoftware.** {*;}
-keep class org.apache.** {*;}
-dontwarn  com.easemob.**

這是我在項目中使用到的整個代碼混淆的內容。

什麼是代碼混淆

Java 是一種跨平臺的、解釋型語言,Java 源代碼編譯成中間”字節碼”存儲於 class 文件中。由於跨平臺的需要,Java 字節碼中包括了很多源代碼信息,如變量名、方法名,並且通過這些名稱來訪問變量和方法,這些符號帶有許多語義信息,很容易被反編譯成 Java 源代碼。爲了防止這種現象,我們可以使用 Java 混淆器對 Java 字節碼進行混淆。

混淆就是對發佈出去的程序進行重新組織和處理,使得處理後的代碼與處理前代碼完成相同的功能,而混淆後的代碼很難被反編譯,即使反編譯成功也很難得出程序的真正語義。被混淆過的程序代碼,仍然遵照原來的檔案格式和指令集,執行結果也與混淆前一樣,只是混淆器將代碼中的所有變量、函數、類的名稱變爲簡短的英文字母代號,在缺乏相應的函數名和程序註釋的況下,即使被反編譯,也將難以閱讀。同時混淆是不可逆的,在混淆的過程中一些不影響正常運行的信息將永久丟失,這些信息的丟失使程序變得更加難以理解。

混淆器的作用不僅僅是保護代碼,它也有精簡編譯後程序大小的作用。由於以上介紹的縮短變量和函數名以及丟失部分信息的原因, 編譯後 jar 文件體積大約能減少25% ,這對當前費用較貴的無線網絡傳輸是有一定意義的。

代碼混淆的方法

根據 SDK 的版本不同有 2 中不同的代碼混淆方式,以上的 proguard.cfg 參數詳解中所涉及到的信息是在較低版本 SDK 下的混淆腳本,事實上在高版本的 SDK 下混淆的原理和參數也與低版本的相差無幾,只是在不同 SDK 版本的環境下引入混淆腳本的方式有所不同。具體方法如下:

  • 低版本

低版本 SDK 下,項目中同時包含 proguard.cfg 和 project.properties 文件,則只需在 project.properties 文件末尾添加 proguard.config=proguard.cfg 再將項目 Export 即可。
我的項目中的proguard.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 edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

# Project target.

target=android-19
proguard.config=proguard.cfg
android.library=false
  • 高版本

高版本 SDK 下,項目中同時包含 proguard-project.txt 和 project.properties 文件,這時需要在 proguard-project.txt 文件中進行如下信息的配置,然後再將項目 Export 即可。

# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

下面給出代碼混淆時候可能遇到的問題:

加入第三方jar包之後常出現的幾個異常
proguard returned with error code 1.See console
情況1:
Proguard returned with error code 1. See console
Error: C:/Documents (系統找不到指定文件)
後來發現是因爲將整個工程放到了桌面上,而桌面的目錄是C:/Documents and Settings/Administrator/桌面,在這裏面有空格,而proguard進行發編譯的時候是不允許有空格的
如果換了正確路徑還不好用的話,直接刪除proguard就好了
注意:SDK和程序路徑最好不要有空格符

情況2:
Proguard returned with error code 1. See console
異常:
java.lang.ArrayIndexOutOfBoundsException
解決辦法:將proguard.cfg中的”-dontpreverify”改成“-dontoptimize”
參考文章:http://groups.google.com/group/android-developers/browse_thread/thread/eca3b0f5ce6ad00f

我把項目中生成的proguard文件夾(此時文件夾是空的)刪掉,然後再重新運行項目,就OK 了。

情況3:
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] Proguard returned with error code 1. See console
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] java.io.IOException: Can’t read [proguard.ClassPathEntry@106082] (No such file or directory)
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] at proguard.InputReader.readInput(InputReader.java:230)
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] at proguard.InputReader.readInput(InputReader.java:200)
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] at proguard.InputReader.readInput(InputReader.java:178)
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] at proguard.InputReader.execute(InputReader.java:100)
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] at proguard.ProGuard.readInput(ProGuard.java:195)
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] at proguard.ProGuard.execute(ProGuard.java:78)
[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] at proguard.ProGuard.main(ProGuard.java:499)
拋出這樣的異常的原因是第三方jar的引用路徑不對,沒有找到這個需要忽略混淆的jar包。
參考:http://stackoverflow.com/questions/4884456/android-proguard-java-io-ioexception-cant-read-proguard-classpathentry

情況4:
1,android-support-v4.jar報錯的話,要加上下面的代碼
-ignorewarnings
-dontwarn android.support.v4.**
-keep class android.support.v4.* { ; }
-keep interface android.support.v4.app.* { ; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment
2,所有的*.jar包都要加上
-libraryjars libs/*.jar
3,混淆代碼除了可以更安全還有一個好處是:你的APK文件變得更小,大概爲混淆之前的1/2吧。

參考地址:http://www.cnblogs.com/sunzn/archive/2013/03/06/2946952.html
http://blog.csdn.net/fhl13017599952/article/details/24265831

發佈了110 篇原創文章 · 獲贊 60 · 訪問量 66萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章