【實習總結篇】一.混淆代碼

博主最近也去實習去了,實習後的第一件工作就是混淆代碼快哭了

之前完全沒聽過,於是我就瘋狂的上網查資料。

在Android studio 上的混淆代碼

然後大家看看打包的配置文件build.gradle裏面的一段配置代碼

瞭解一下打包過程。

然後大家看看打包的配置文件build.gradle裏面的一段配置代碼

 //混淆,新版本是ninifyEnabled不再是runproguard
    minifyEnabled true
 //加載默認混淆配置文件及自定義混淆 配置
   proguardFiles getDefaultProguardFile(‘proguard-android.txt’),’proguard.cfg’

後面是一個混淆模板,貼在 proguard-rules.pro文件上
#指定代碼的壓縮級別
-optimizationpasses 5
#包明不混合大小寫
-dontusemixedcaseclassnames
#不去忽略非公共的庫類
-dontskipnonpubliclibraryclasses
 #優化  不優化輸入的類文件
-dontoptimize
 #預校驗
-dontpreverify
 #混淆時是否記錄日誌
-verbose
 # 混淆時所採用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保護註解
-keepattributes *Annotation*
# 保持哪些類不被混淆
-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
#如果有引用v4包可以添加下面這行
-keep public class * extends android.support.v4.app.Fragment
#忽略警告
-ignorewarning
#####################記錄生成的日誌數據,gradle build時在本項目根目錄輸出################
#apk 包內所有 class 的內部結構
-dump class_files.txt
#未混淆的類和成員
-printseeds seeds.txt
#列出從 apk 中刪除的代碼
-printusage unused.txt
#混淆前後的映射
-printmapping mapping.txt
#####################記錄生成的日誌數據,gradle build時 在本項目根目錄輸出-end################
################<span></span>混淆保護自己項目的部分代碼以及引用的第三方jar包library#########################
#-libraryjars libs/umeng-analytics-v5.2.4.jar
#-libraryjars libs/alipaysd<span></span>k.jar
#<span></span>-libraryjars libs/alipaysecsdk.jar
#-libraryjars libs/alipayutdid.jar
#-libraryjars libs/wup-1.0.0-SNAPSHOT.jar
#-libraryjars libs/weibosdkcore.jar
#三星應用市場需要添加:sdk-v1.0.0.jar,look-v1.0.1.jar
#-libraryjars libs/sdk-v1.0.0.jar
#-libraryjars libs/look-v1.0.1.jar
#我是以libaray的形式引用了一個圖片加載框架,如果不想混淆 keep 掉
-keep class com.nostra13.universalimageloader.** { *; }
#友盟
-keep class com.umeng.**{*;}
#支付寶
-keep class com.alipay.android.app.IAliPay{*;}
-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.lib.ResourceMap{*;}
#信鴿推送
-keep class com.tencent.android.tpush.**  {* ;}
-keep class com.tencent.mid.**  {* ;}
#自己項目特殊處理代碼
#忽略警告
-dontwarn com.veidy.mobile.common.**
#保留一個完整的包
-keep class com.veidy.mobile.common.** {
    *;
 }
-keep class  com.veidy.activity.login.WebLoginActivity{*;}
-keep class  com.veidy.activity.UserInfoFragment{*;}
-keep class  com.veidy.activity.HomeFragmentActivity{*;}
-keep class  com.veidy.activity.CityActivity{*;}
-keep class  com.veidy.activity.ClinikActivity{*;}
#如果引用了v4或者v7包
-dontwarn android.support.**
############<span></span>混淆保護自己項目的部分代碼以及引用的第三方jar包library-end##################
-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*(...);
}
#保持 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);
}
#保持自定義控件類不被混淆
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
#保持 Serializable 不被混淆
-keepnames class * implements java.io.Serializable
#保持 Serializable 不被混淆並且enum 類也不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields><span></span>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
#保持枚舉 enum 類不被混淆 如果混淆報錯,建議直接使用上面的 -keepclassmembers class *implements java.io.Serializable即可
#-keepclassmembers enum * {
#  public static **[] values();
#  public static ** valueOf(java.lang.String);
#}
-keepclassmembers class * {
    public void *ButtonClicked(android.view.View);
}
#不混淆資源類
-keepclassmembers class **.R$* {
    public static <fields>;
}
#避免混淆泛型 如果混淆報錯建議關掉
#–keepattributes Signature
#移除log 測試了下沒有用還是建議自己定義一個開關控制是否輸出日誌
#-assumenosideeffects class android.util.Log {
#    public static boolean isLoggable(java.lang.String, int);
#    public static int v(...);
#    public static int i(...);
#    public static int w(...);
#    public static int d(...);
#    public static int e(...);
#}

在混淆過程中可能會遇到一些錯誤

Android引用第三方jar包混淆時打包報錯(can't find referenced class)
項目打包的時候,總是失敗,提示Proguardreturned with error code 1. See console。然後看控制檯,報出好多can't findreferenced class......
場景:項目中引用了第三方的jar包
原因:第三方jar包中引用了好多oracle發佈的java標準中(也就是我們常用的JDK)包含的類,但是Android的java標準和oracle的不一樣,android.jar裏面去掉了oraclejava標準中好多用不到的包和類。
解決辦法:首先要把你項目中所引入的第三方jar包使用"-libraryjars包路徑"指定好。然後,用-dontwarncom.xx.bbb.**
-keep class com.xx.bbb.** {*;}
告訴proguard.cfg不用混淆指定的jar包,也不用提示這個包所報出的錯。這樣就ok了。
注意:要是用dontwarn取消指定包報錯之前,你要保證第三方引用的類在你的項目中沒有用到。


Android混淆後項目運行的時候出現異常(混淆之前沒有該異常)
1、ClassNotFoundException,NoSuchMethodError
原因:這種異常會在好多情況下出現,比如:本地代碼通過反射調用其他的類,但是經過了混淆之後,就會出現如上異常;調用了JNI之後,C或者C++和java代碼進行交互的時候找不到java的類或者方法,導致發生了異常......等等,還有好多。
解決辦法:只需要將被調用的java類標註爲不混淆即可。-keepclass package.classname{*;}
2、ExceptionInInitializerError
原因:這是由於類初始化的時候發生了異常。
解決辦法:找到具體是哪裏的類哪個方法哪個類初始化的時候發生的異常,然後解決問題。
注:遇到這個錯誤,首先要確認是不是因爲第三方的jar包導致的。如果不是的話,就找本地代碼,看是不是寫的有問題。如果確實是因爲第三方jar包的代碼導致的,儘量找到源碼或者反編譯,查看問題到底是什麼引起的,然後找到相應的配置在proguard裏面配置。
例如:我們項目中碰到過一個問題,就是因爲第三方的jar包裏面有一個字段初始化的時候報了空指針,然後導致我們的代碼報了上面的錯。當時很奇怪,爲什麼第三方的jar包還能報錯,最後調查了之後才發現,是因爲人家用到了類的註解,而proguard在混淆優化的時候把註解去掉了,所以報了空指針,只需要在proguard裏面加上保護註解就可以了-keepattributes*Annotation*
3、ClassCastException
原因:類強制轉換的時候出錯。
解決辦法:找到代碼,看是代碼寫的問題,還是混淆後的問題。如果沒有混淆正常運行的話,一般都是因爲混淆後遇到了各種問題才報的錯。我們項目中遇到的問題是因爲沒有讓proguard保持泛型,所以強轉的時候報錯。只需要在proguard文件裏面加上泛型即可-keepattributesSignature
4、Resources$NotFoundException(resource not found)
資源沒有找到,是因爲第三方jar包或者自己的代碼是通過反射獲得R文件中的資源,所以需要將R文件屏蔽掉
原因:代碼進行了混淆,R文件沒有了,所以通過反射獲取的R文件找不到
 解決辦法:在proguard文件裏設置不混淆R文件 -keep class **.R$* { *; }


大家如果遇到其他的異常,可以在下面提出來,希望可以幫助大家解決問題。

過幾天在補充

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