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中加入如下代碼,基本能夠涵蓋全部:html

-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」 錯誤。java

 

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

-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.**

忽略了全部庫,若是還報警,能夠把報警的也所有忽略。android

 

-------------------------------------------------------------------------正則表達式

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

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

2.若是使用了自定義控件那麼要保證它們不參與混淆。json

3.若是使用了枚舉要保證枚舉不被混淆。api

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

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
相關文章
相關標籤/搜索