[轉]Android Studio實現代碼混淆


 

 1,在build.grandle添加,其中規則寫在proguard-rules.pro中,也可以自定義一個文件,將其代替,比如eclipse常用的 proguard-project.txt:

 

buildTypes {
  release {
    signingConfig signingConfigs.release
    minifyEnabled true      # 設置是否進行 shrink 等操作(即無用代碼壓縮),一般設置為 true,使混淆更有效
    proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
  }
}

2,在proguard-rules.pro中加入以下代碼,基本可以涵蓋所有:

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

-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 * extends android.app.backup.BackupAgentHelper # 保持哪些類不被混淆
-keep public class * extends android.preference.Preference        # 保持哪些類不被混淆
-keep public class com.android.vending.licensing.ILicensingService    # 保持哪些類不被混淆

-keepclasseswithmembernames class * {  # 保持 native 方法不被混淆
    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);
}
-keepclassmembers enum * {     # 保持枚舉 enum 類不被混淆    
    public static **[] values();    
    public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable { # 保持 Parcelable 不被混淆  
    public static final android.os.Parcelable$Creator *;
}

3,通過 Android Studio進行 混淆代碼時,默認已經將 lib目錄中的 jar 都已經添加到打包腳本中,所以不需要再次手動添加,否則會出現“ java.io.IOException: The same input jar is specified twice” 錯誤。

 

推薦將你所有引用的庫(在 app/build.gradle 里)全部不混淆,里面的groupid就是package,將package加入就行了,這是我的示例:

-keep class org.greenrobot.greendao.** { *; }
-dontwarn org.greenrobot.greendao.**
-keep class com.jakewharton.** { *; }
-dontwarn com.jakewharton.**
-keep class io.reactivex.** { *; }
-dontwarn io.reactivex.**
-keep class org.jsoup.** { *; }
-dontwarn org.jsoup.**
-keep class com.squareup.retrofit2.** { *; }
-dontwarn com.squareup.retrofit2.**
-keep class com.scottyab.** { *; }
-dontwarn com.scottyab.**
-keep class com.pddstudio.preferences.encrypted.** { *; }
-dontwarn com.pddstudio.preferences.encrypted.**

忽略了所有庫,如果還報警,可以把報警的也全部忽略。

 

-------------------------------------------------------------------------

ProGuard默認會對第三方庫也進行混淆的,而第三方庫有的已經混淆過了,有的使用了Java反射技術,所以我們在進行代碼混淆的時候要排除這些第三方庫。排除對第三方庫的混淆需要在混淆規則文件(通常是:proguard-project.txt或proguard.cfg或proguard-rules.pro或proguard-rules.txt也可以是其它的文件名只要在配置文件中將含有混淆規則的文件名配置進去就行了)中添加如下規則:

1.如果使用了Gson之類的工具要使JavaBean類即實體類不被混淆。

2.如果使用了自定義控件那么要保證它們不參與混淆。

3.如果使用了枚舉要保證枚舉不被混淆。

4.對第三方庫中的類不進行混淆

a.混淆時保護引用的第三方jar包

如:-libraryjars libs/baidumapapi_v3_2_0.jar  #保護引用的第三方jar包不被混淆

注意:在使用Eclipse+ADT時需要加入-libraryjars libs/...,如果你是使用Android Studio開發的項目則不需要加入libs包中的jar包,這是因為,通過Android Studio進行混淆代碼時,默認已經將 lib目錄中的 jar 都已經添加到打包腳本中,所以不需要再次手動添加,否則會出現“ java.io.IOException: The same input jar is specified twice” 錯誤。

b.混淆時保護第三方jar包中的類不被混淆

如:-keep class com.baidu.** { *; }         #保持com.baidu.**這個包里面的所有類和所有方法不被混淆。

-dontwarn com.baidu.**          #讓ProGuard不要警告找不到com.baidu.**這個包里面的類的相關引用

附:下面是開發中用到的一些混淆規則,大家可以根據需要復制到自己的項目中的混淆規則的文件中:

################common###############  
-keep class com.jph.android.entity.** { *; } #實體類不參與混淆  
-keep class com.jph.android.view.** { *; } #自定義控件不參與混淆  
  
################baidu map###############  
-libraryjars libs/baidumapapi_v3_2_0.jar  
-libraryjars libs/locSDK_5.0.jar  
-keep class com.baidu.** { *; }  
-keep class vi.com.gdi.bgl.android.**{*;}  
-dontwarn com.baidu.**  
  
  
################afinal##################  
#-libraryjars libs/afinal_0.5_bin.jar  
#-keep class net.tsz.afinal.** { *; }   
#-keep public class * extends net.tsz.afinal.**    
#-keep public interface net.tsz.afinal.** {*;}  
#-dontwarn net.tsz.afinal.**  
  
################xutils##################  
-libraryjars libs/xUtils-2.6.14.jar  
-keep class com.lidroid.xutils.** { *; }   
-keep public class * extends com.lidroid.xutils.**    
-keepattributes Signature  
-keepattributes *Annotation*  
-keep public interface com.lidroid.xutils.** {*;}  
-dontwarn com.lidroid.xutils.**  
-keepclasseswithmembers class com.jph.android.entity.** {  
    <fields>;  
    <methods>;  
}  
  
################支付寶##################  
-libraryjars libs/alipaysecsdk.jar  
-libraryjars libs/alipayutdid.jar  
-libraryjars libs/alipaysdk.jar  
-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{*;}  
  
################gson##################  
-libraryjars libs/gson-2.2.4.jar  
-keep class com.google.gson.** {*;}  
#-keep class com.google.**{*;}  
-keep class sun.misc.Unsafe { *; }  
-keep class com.google.gson.stream.** { *; }  
-keep class com.google.gson.examples.android.model.** { *; }   
-keep class com.google.** {  
    <fields>;  
    <methods>;  
}  
-keepclassmembers class * implements java.io.Serializable {  
    static final long serialVersionUID;  
    private static final java.io.ObjectStreamField[] serialPersistentFields;  
    private void writeObject(java.io.ObjectOutputStream);  
    private void readObject(java.io.ObjectInputStream);  
    java.lang.Object writeReplace();  
    java.lang.Object readResolve();  
}  
-dontwarn com.google.gson.**  
  
  
  
################httpmime/httpcore##########  
-libraryjars libs/httpcore-4.3.2.jar  
-libraryjars libs/httpmime-4.3.5.jar  
-keep class org.apache.http.** {*;}  
-dontwarn org.apache.http.**  
  
####################jpush##################  
-libraryjars libs/jpush-sdk-release1.7.1.jar  
-keep class cn.jpush.** { *; }  
-keep public class com.umeng.fb.ui.ThreadView { } #雙向反饋功能代碼不混淆  
-dontwarn cn.jpush.**  
-keepclassmembers class * {  
    public <init>(org.json.JSONObject);  
}  
 #不混淆R類  
-keep public class com.jph.android.R$*{   
    public static final int *;  
}  
-keepclassmembers enum * {  
    public static **[] values();  
    public static ** valueOf(java.lang.String);  
}  
  
####################umeng##################  
-libraryjars libs/umeng-analytics-v5.2.4.jar  
-keep class com.umeng.analytics.** {*;}  
-dontwarn com.umeng.analytics.**  
  
#-keep public class * extends com.umeng.**    
#-keep public class * extends com.umeng.analytics.**    
#-keep public class * extends com.umeng.common.**    
#-keep public class * extends com.umeng.newxp.**   
-keep class com.umeng.** { *; }    
-keep class com.umeng.analytics.** { *; }    
-keep class com.umeng.common.** { *; }    
-keep class com.umeng.newxp.** { *; }   
  
-keepclassmembers class * {  
   public <init>(org.json.JSONObject);  
}  
-keep class com.umeng.**  
  
-keep public class com.idea.fifaalarmclock.app.R$*{  
    public static final int *;  
}  
  
-keep public class com.umeng.fb.ui.ThreadView {  
}  
  
-dontwarn com.umeng.**  
  
-dontwarn org.apache.commons.**  
  
-keep public class * extends com.umeng.**  
  
-keep class com.umeng.** {*; }  
  
####################universal-image-loader########  
-libraryjars libs/universal-image-loader-1.9.3.jar  
-keep class com.nostra13.universalimageloader.** {*;}  
-dontwarn com.nostra13.universalimageloader.**  
  
  
####################zxing#####################  
-libraryjars libs/zxing.jar  
-libraryjars libs/zxing_apply.jar  
-keep class com.google.zxing.** {*;}  
-dontwarn com.google.zxing.**  
  
####################BASE64Decoder##################  
-libraryjars libs/sun.misc.BASE64Decoder.jar  
  
####################support.v4#####################  
-libraryjars libs/android-support-v4.jar  
-keep class android.support.v4.** { *; }  
-dontwarn android.support.v4.**  
  
###################other####################  
# slidingmenu 的混淆  
-dontwarn com.jeremyfeinstein.slidingmenu.lib.**  
-keep class com.jeremyfeinstein.slidingmenu.lib.** { *; }  
# ActionBarSherlock混淆  
-dontwarn com.actionbarsherlock.**  
-keep class com.actionbarsherlock.** { *; }  
-keep interface com.actionbarsherlock.** { *; }  
-keep class * extends java.lang.annotation.Annotation { *; }  
-keepclasseswithmembernames class * {  
    native <methods>;  
}  
  
-keep class com.jph.android.entity.** {  
    <fields>;  
    <methods>;  
}  
  
-dontwarn android.support.**  
-dontwarn com.slidingmenu.lib.app.SlidingMapActivity  
-keep class android.support.** { *; }  
-keep class com.actionbarsherlock.** { *; }  
-keep interface com.actionbarsherlock.** { *; }  
-keep class com.slidingmenu.** { *; }  
-keep interface com.slidingmenu.** { *; }  

 

 如果打包的時候出現警告:can't find referenced class  怎么辦?解決方案如下:

1. 問題的產生原因

           "類1 can't find referenced class 類2" 字面上的意思就是類1找不到類2的引用;接着再看下去"You may need to specify additional library jars (using '-libraryjars').";

噢,原來這么簡單呀,他說我需要使用-libraryjars加上項目中使用到的第三方庫就OK了。好!馬上把"-libraryjars ./libs/xx.jar"這段代碼加入到proguard.cfg配置文件里面去,
再export一次!一分鍾過后,靠!同樣的錯誤提示又來了:

[java]  view plain copy
  1. Warning: com.xxx.bbbb.F.H$3: can't find referenced class com.xxx.bbbb..F.H$com.xxx.bbbb.F.H$_B  
  2. Warning: there were 1 unresolved references to classes or interfaces.  
  3. You may need to specify additional library jars (using '-libraryjars').  
  4. java.io.IOException: Please correct the above warnings first.  
  5.     at proguard.Initializer.execute(Initializer.java:321)  
  6.     at proguard.ProGuard.initialize(ProGuard.java:211)  
  7.     at proguard.ProGuard.execute(ProGuard.java:86)  
  8.     at proguard.ProGuard.main(ProGuard.java:492)  


          這不是坑爹嗎?還報錯!我以為是順序不對,把-libraryjars ./libs/xx.jar這句話放到最開頭,或者在keep...語句的開頭,結果很悲催,也不行。馬上看看官方文檔的Troubleshooting,發現有說到這個問題后,大喜!我們一起去瞧瞧他怎么說的:

[java]  view plain copy
  1. Warning: can't find superclass or interface  
  2. Warning: can't find referenced class  
  3. If there are unresolved references to classes or interfaces, you most likely forgot to specify an essential library.   
  4. For proper processing, all libraries that are referenced by your code must be specified, including the Java run-time library.   
  5. For specifying libraries, use the -libraryjars option.  
  6. For example, if ProGuard complains that it can't find a javax.crypto class, you probably still have to specify jce.jar, next to the more common rt.jar.  
  7. If you're missing a library and you're absolutely sure it isn't used anyway, you can try your luck with the -ignorewarnings option, or even the -dontwarn option. Only use these options if you really know what you're doing though.  
  8. For example, if you're developing for Android, and ProGuard complains that it can't find a java.awt class, then some library that you are using is referring to java.awt.   
  9. This is a bit shady, since Android doesn't have this package at all, but if your application works anyway, you can let ProGuard accept it with "-dontwarn java.awt.**".  


2.官方對於這個問題的解釋:

          如果存在未解決的類或者接口的引用的話,你很有可能忘記指定一些必要的庫了。正確的處理方法是在你代碼里引用到的所有庫都必須要在配置文件中指定,包括Java運行庫,使用-libraryjars選項來指定這些庫。

          看到這里,你明白了剛剛為什么提示You may need to specify additional library jars (using '-libraryjars').了吧,目的就是在配置文件里面加上項目中所使用到的第三方庫。可是,你這是坑爹呀,我明明給所有庫都加上-libraryjars參數指定了,結果還是報Warning: com.xxx.bbbb.F.H$3: can't find referenced class com.xxx.bbbb..F.H$com.xxx.bbbb.F.H$_B這個錯啊,打包不了!

 

          好,我們再看下去...

 

          接着他給我們舉個例子:如果ProGuard說它找不到javax.crypto class這個類,你可能還需要指定jce.jar包,緊接着還要指定更常用的rt.jar包。換句話說,javax.crypto class這個類里面所引用到的類不但在jce.jar包里面,還在rt.jar包里面。

可是我項目中用到的所有第三方包都使用-libraryjars指定了呀!這個方法解決不了我的問題,不知道解決得了你的問題不?

 

          解決不了的話,再看下去...

 

          如果你缺少了某個庫,而且你絕對肯定自己沒有用到這個庫里面的類的話,你可以試試你的運氣,使用-ignorewarnings或者-dontwarn選項!-dontwarn我試過了,加上
-dontwarn com.xxx.bbbb.**之后確實沒有報錯,可以打包出來了!呵呵,別高興得太早,你拿你這樣打包好了的包去運行一下試試看?如果運氣好的話,程序沒有執行到找不到的類那里就不會報錯,如果運氣不好的話執行到那里了就會拋ClassNotFoundException!哼哼,怕了沒?

          我們身為備受矚目的程序猿,肯定要有職業道德的,總不能編譯出來的程序要使用到用戶的運氣+人品才能保證不出錯吧!!^_^

其實,我明白他說的意思的,就是說你要絕對確保這個類沒有被你的程序中使用到才可以使用-ignorewarnings或者-dontwarn選項,接着,他又舉了個例子了: 比如你開發的是Android項目,但是打包時ProGuard抱怨找不到java.awt里面的某些類,可能是因為你使用的某些庫要用到java.awt包里面的類,眾所周知,Android壓根就沒有java.awt這個包,它是J2SE里面的包,我們Android程序當然不需要這個包也能很好的運行了,此時,你可以用-dontwarn java.awt.**來屏蔽掉所有關於java.awt的警告他舉這個例子是為了說明一個理論:當你絕對確定自己的代碼沒有用到報錯的這個類后,可以使用-dontwarn com.xx.bbb**來屏蔽警告信息



3.總結出官方對於
Warning: can't find superclass or interface
Warning: can't find referenced class

這兩個問題的解決方法:

1.要把你項目中所引入的第三方jar包使用"-libraryjars 包路徑"指定好。
2.還是報錯的話,確保報錯的類沒有在你的項目中使用到,使用"-dontwarn 類名正則表達式"屏蔽警告。
完了?可是我還想問:第一步做完后還是報錯,而且這個類在我項目中真的有用到,不能使用"-dontwarn .."屏蔽警告啊??


4.說了這么久,終於開始說解決方案了:

          其實找不到引用的這個類是第三方包里面的,而且很多時候我們只需要混淆自己寫的代碼就行了,第三方包的代碼就是否要打亂就不要管了。嘻嘻,這叫做"只掃自己門前雪,甭管他人瓦上霜",

我們可以使用
-dontwarn com.xx.bbb.**
-keep class com.xx.bbb.** { *;}

參數來保持第三方庫中的類而不亂,-dontwarn和-keep 結合使用,意思是保持com.xx.bbb.**這個包里面的所有類和所有方法而不混淆,接着還叫ProGuard不要警告找不到com.xx.bbb.**這個包里面的類的相關引用。
配置好后,重新打包,一切OK!而且程序能正確運行。示例:

----------------------------------------- question ------------------------------------------------

After some updates in Android SDK manager I try make signed apk and get this:

ProGuard: [] Warning: com.google.android.gms.auth.GoogleAuthUtil: can't find referenced class com.welhzh.android.gms.R ProGuard: [] Warning: com.google.android.gms.auth.GoogleAuthUtil: can't find referenced class com.google.android.gms.R$string ... etc.

If set -dontwarn com.welhzh.android.gms.** compiling is OK. But after run I get error many reports like this (from many devices):

Caused by: android.view.InflateException: Binary XML file line #32:  Error inflating class com.google.android.gms.common.SignInButton

On my devices all ok. Before update I have not ProGuard warnings and all work perfectly. How it fix?

----------------------------------------- answer ------------------------------------------------

Although adding this to proguard-project.txt file works, it keeps all classes.

-keep class com.welhzh.android.gms.** { *; }
-dontwarn com.welhzh.android.gms.**

I prefer this, which makes apk file size much smaller  (一般情況下別用這個) :

-keep public class com.welhzh.android.gms.* { public *; }
-dontwarn com.welhzh.android.gms.**

Also note up to date Google Play Proguard notification here:http://developer.android.com/google/play-services/setup.html#Proguard

-keep class * extends java.util.ListResourceBundle {
    protected Object[][] getContents();
}

-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
    public static final *** NULL;
}

-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
    @com.google.android.gms.common.annotation.KeepName *;
}

-keepnames class * implements android.os.Parcelable {
    public static final ** CREATOR;
}

 

 如果上面的導致app運行時崩潰,可以來狠一點的,指定proguard只混淆某些package或類:

-keep class !com.foo.**,!com.bar.** { *; }
-dontwarn !com.foo.**,!com.bar.**     # 這句比較危險,不提示任何warning

 

 


---------------------
作者:微信公眾號--共鳴圈
來源:CNBLOGS
原文:https://www.cnblogs.com/welhzh/p/6017434.html
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM