天天看點

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

Android Studio相關部落格:

Android Studio(一):介紹、安裝、配置

Android Studio(二):快捷鍵設定、插件安裝

Android Studio(三):設定Android Studio編碼 Android Studio(四):Android Studio內建Genymotion Android Studio(五):修改Android Studio項目包名 Android Studio(六):Android Studio添加注釋模闆 Android Studio(七):項目從Eclipse到Android Studio遷移 Android Studio(八):Android Studio設定教程 Android Studio(九):引用jar及so檔案 Android Studio(十):添加assets目錄 Android Studio(十一):代碼混淆及打包apk Android Studio(十二):打包多個釋出管道的apk檔案

  最近終于把項目做完了,天天加班,累成狗了。 而昨日又忽聞慕和網絡CEO吳波猝然離世的消息,深感網際網路行業在高薪(其實好多人并不高薪哇

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案
Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案
Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

)的同時,也是高壓力高風險的啊,也在此希望廣大同行可以珍惜生命,遠離代碼,啊呸,是遠離加班熬夜!

  好啦,繼續今天的話題,當項目做完之後,作為一個稱職的開發者,接下來任務自然是打包測試釋出了。

  而打包之前,你必須要混淆你的代碼,前提是你不希望别人看到你的代碼!

  如果你不混淆你的代碼,會有怎樣的後果呢?知道不?

  通過反編譯你的apk檔案,你的源代碼和資源檔案都将暴漏無疑,就像光着屁股在别人眼瞎亂晃一樣,我覺得它們一定不好受。 作為一手造就它的你來說,怎麼能讓它不好受呢?

  嘿,說到這裡,我想有些初學的開發者已經會有所好奇了:如何反編譯apk檔案擦檢視源碼呢?再此,給大家推薦兩篇部落格,很精簡很易懂《android 代碼 混淆- 原來如此簡單》和 《 Android APK反編譯就這麼簡單 詳解》; 相信你看完這兩篇部落格(能跟着做一遍更佳),一定會覺得蛋疼: 尼瑪老子辛辛苦苦搞了幾個月的項目,你幾分鐘就把源碼給我搞到了,當我開源的啊!

 好啦,知道不去混淆代碼會有怎樣的影響之後,那我們來看看如何在Android Studio上混淆你的工程代碼吧。

代碼混淆

首先,在你的工程目錄下,找到proguard-rules.pro檔案,它就是你要進行編寫混淆配置的檔案:

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

光編寫該檔案還不夠哦,你還需要在你module的build.gradle檔案中引用該混淆檔案:

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

好了,知道在哪配置混淆檔案後,下面開始講講如何配置混淆:

混淆檔案 proguard-rules.pro 參數詳解:

[plain]  view plain  copy  print ?

  1. -optimizationpasses 5                                                           # 指定代碼的壓縮級别  
  2. -dontusemixedcaseclassnames                                                     # 是否使用大小寫混合  
  3. -dontskipnonpubliclibraryclasses                                                # 是否混淆第三方jar  
  4. -dontpreverify                                                                  # 混淆時是否做預校驗  
  5. -verbose                                                                        # 混淆時是否記錄日志  
  6. -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*        # 混淆時所采用的算法  
  7. -keep public class * extends android.app.Activity                               # 保持哪些類不被混淆  
  8. -keep public class * extends android.app.Application                            # 保持哪些類不被混淆  
  9. -keep public class * extends android.app.Service                                # 保持哪些類不被混淆  
  10. -keep public class * extends android.content.BroadcastReceiver                  # 保持哪些類不被混淆  
  11. -keep public class * extends android.content.ContentProvider                    # 保持哪些類不被混淆  
  12. -keep public class * extends android.app.backup.BackupAgentHelper               # 保持哪些類不被混淆  
  13. -keep public class * extends android.preference.Preference                      # 保持哪些類不被混淆  
  14. -keep public class com.android.vending.licensing.ILicensingService              # 保持哪些類不被混淆  
  15. -keepclasseswithmembernames class * {                                           # 保持 native 方法不被混淆  
  16.     native <methods>;  
  17. }  
  18. -keepclasseswithmembers class * {                                               # 保持自定義控件類不被混淆  
  19.     public <init>(android.content.Context, android.util.AttributeSet);  
  20. }  
  21. -keepclasseswithmembers class * {  
  22.     public <init>(android.content.Context, android.util.AttributeSet, int);     # 保持自定義控件類不被混淆  
  23. }  
  24. -keepclassmembers class * extends android.app.Activity {                        # 保持自定義控件類不被混淆  
  25.    public void *(android.view.View);  
  26. }  
  27. -keepclassmembers enum * {                                                      # 保持枚舉 enum 類不被混淆  
  28.     public static **[] values();  
  29.     public static ** valueOf(java.lang.String);  
  30. }  
  31. -keep class * implements android.os.Parcelable {                                # 保持 Parcelable 不被混淆  
  32.   public static final android.os.Parcelable$Creator *;  
  33. }  
  34. -keep class MyClass;                                                            # 保持自己定義的類不被混淆  

以上是最基礎的配置,幾乎每個項目都需要進行這些地方的混淆(或保持不混淆)。

如果你仔細看過上方的注釋,就會了解一些基本代碼混淆政策了。 

隻是,這還遠遠不夠,因為你在項目中,總會不可避免的引用第三方的library庫或是jar包,那,如果你不能夠正确的混淆第三方的資源,可能會導緻你的應用無法使用。(我就因為忘了配置Gson相關的混淆,導緻頁面一直沒有資料顯示,蛋疼的一筆)。

貼出我項目中關于第三方的混淆部分:

[plain]  view plain  copy  print ?

  1. #如果有引用v4包可以添加下面這行  
  2. -keep class android.support.v4.** { *; }  
  3. -keep public class * extends android.support.v4.**  
  4. -keep public class * extends android.app.Fragment  
  5. #如果引用了v4或者v7包,可以忽略警告,因為用不到android.support  
  6. -dontwarn android.support.**  
  7. #保持自定義元件不被混淆  
  8. -keep public class * extends android.view.View {  
  9.     public <init>(android.content.Context);  
  10.     public <init>(android.content.Context, android.util.AttributeSet);  
  11.     public <init>(android.content.Context, android.util.AttributeSet, int);  
  12.     public void set*(...);  
  13. }  
  14. #保持 Serializable 不被混淆  
  15. -keepnames class * implements java.io.Serializable  
  16. #保持 Serializable 不被混淆并且enum 類也不被混淆  
  17. -keepclassmembers class * implements java.io.Serializable {  
  18.     static final long serialVersionUID;  
  19.     private static final java.io.ObjectStreamField[] serialPersistentFields;  
  20.     private void writeObject(java.io.ObjectOutputStream);  
  21.     private void readObject(java.io.ObjectInputStream);  
  22.     java.lang.Object writeReplace();  
  23.     java.lang.Object readResolve();  
  24. }  
  25. #保持枚舉 enum 類不被混淆 如果混淆報錯,建議直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可  
  26. -keepclassmembers enum * {  
  27.   public static **[] values();  
  28.  public static ** valueOf(java.lang.String);  
  29. }  
  30. -keepclassmembers class * {  
  31.     public void *ButtonClicked(android.view.View);  
  32. }  
  33. #不混淆資源類  
  34. #-keepclassmembers class **.R$* {  
  35. #    public static <fields>;  
  36. #}  
  37. #xUtils(保持注解,及使用注解的Activity不被混淆,不然會影響Activity中你使用注解相關的代碼無法使用)   
  38. -keep class * extends java.lang.annotation.Annotation {*;}  
  39. -keep class com.otb.designerassist.activity.** {*;}  
  40. #自己項目特殊處理代碼(這些地方我使用了Gson類庫和注解,是以不希望被混淆,以免影響程式)  
  41. -keep class com.otb.designerassist.entity.** {*;}  
  42. -keep class com.otb.designerassist.http.rspdata.** {*;}  
  43. -keep class com.otb.designerassist.service.** {*;}  
  44. ##混淆保護自己項目的部分代碼以及引用的第三方jar包library(想混淆去掉"#")  
  45. #-libraryjars libs/umeng-analytics-v5.2.4.jar  
  46. #-libraryjars libs/alipaysecsdk.jar  
  47. #-libraryjars libs/alipayutdid.jar  
  48. #-libraryjars libs/weibosdkcore.jar   
  49. # 以libaray的形式引用的圖檔加載架構,不想混淆(注意,此處不是jar包形式,想混淆去掉"#")  
  50. #-keep class com.nostra13.universalimageloader.** { *; }  
  51. ###-------- Gson 相關的混淆配置--------  
  52. -keepattributes Signature  
  53. -keepattributes *Annotation*  
  54. -keep class sun.misc.Unsafe { *; }  
  55. ###-------- pulltorefresh 相關的混淆配置---------  
  56. -dontwarn com.handmark.pulltorefresh.library.**  
  57. -keep class com.handmark.pulltorefresh.library.** { *;}  
  58. -dontwarn com.handmark.pulltorefresh.library.extras.**  
  59. -keep class com.handmark.pulltorefresh.library.extras.** { *;}  
  60. -dontwarn com.handmark.pulltorefresh.library.internal.**  
  61. -keep class com.handmark.pulltorefresh.library.internal.** { *;}  
  62. ###---------  reservoir 相關的混淆配置-------  
  63. -keep class com.anupcowkur.reservoir.** { *;}  
  64. ###-------- ShareSDK 相關的混淆配置---------  
  65. -keep class cn.sharesdk.** { *; }  
  66. -keep class com.sina.sso.** { *; }  
  67. ###--------------umeng 相關的混淆配置-----------  
  68. -keep class com.umeng.** { *; }  
  69. -keep class com.umeng.analytics.** { *; }  
  70. -keep class com.umeng.common.** { *; }  
  71. -keep class com.umeng.newxp.** { *; }  
  72. ###-----------MPAndroidChart圖庫相關的混淆配置------------  
  73. -keep class com.github.mikephil.charting.** { *; }  

以上的配置,即是對一個項目的混淆配置了,相對比較完整,大家可以依葫蘆畫瓢,寫更多的配置,對于一些第三方項目的使用,一般官方會給出如何配置混淆,大家需要小心,别忘了配置。

好啦,如果你已經寫好自己的混淆配置檔案,不要忘了在build.gradle檔案中再次配置下,打開混淆檔案:

[plain]  view plain  copy  print ?

  1. buildTypes {  
  2.        debug {  
  3.            // 顯示Log  
  4.            buildConfigField "boolean", "LOG_DEBUG", "true"  
  5.            versionNameSuffix "-debug"  
  6.            minifyEnabled false  
  7.            zipAlignEnabled false  
  8.            shrinkResources false  
  9.            signingConfig signingConfigs.assist  
  10.        }  
  11.        release {  
  12.            // 不顯示Log  
  13.            buildConfigField "boolean", "LOG_DEBUG", "false"  
  14.            //混淆  
  15.            minifyEnabled true  
  16.            //Zipalign優化  
  17.            zipAlignEnabled true  
  18.            // 移除無用的resource檔案  
  19.            shrinkResources true  
  20.            //加載預設混淆配置檔案  
  21.            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'  
  22.            //簽名  
  23.            signingConfig signingConfigs.<span style="font-family: Arial, Helvetica, sans-serif;">assist</span>  
  24.        }  
  25.    }  

release節點下,minifyEnabled設定為true。

導出APK檔案

  學會了如何混淆你的項目代碼之後,接下來,我們看下,如何使用Android Studio導出APK檔案吧。

(1)Android Studio菜單Build->Generate Signed APK 

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

(2)彈出簽名選擇、建立視窗

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

(3)建立密鑰庫及密鑰,建立後會自動選擇剛建立的密鑰庫和密鑰(已擁有密鑰庫跳過) 

    點選“Create new...”按鈕建立密鑰庫 

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

Key store path:密鑰庫檔案的位址 

Password/Confirm:密鑰庫的密碼 

Alias:密鑰名稱 

Password/Confirm:密鑰密碼 

Validity(years):密鑰有效時間 

First and Last Name:密鑰頒發者姓名 

Organizational Unit:密鑰頒發組織 

City or Locality:城市 

Country Code(XX):國家 

(4)選擇已存在密鑰庫及密鑰(在(3)中建立密鑰庫後跳過此步驟) 

    點選“Choose existing...”按鈕找到密鑰庫檔案 

    Key store password輸入已選擇的密鑰庫檔案的密碼 

    點選Key alias後的“...”按鈕,選擇或者建立一個密鑰 

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

(5)點選“Next”按鈕,選擇儲存路徑後,點選“Finish”按鈕完成 

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

使用Android Studio 自動簽名打包

   a. 打開Project Structure,打開方法如下:

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

   b. 選中需要建構的項目,打開Signing,添加config,建立自己的config

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

   執行完成後,會在build.gradle中自動加上 signingConfigs{ config {...} }的資訊

   c. 打開Build Types -> release

Android studio 代碼混淆及打包apk Android Studio相關部落格: Android Studio(二):快捷鍵設定、插件安裝 代碼混淆 導出APK檔案

    在signing Config中選擇定義的配置

    zip align enabled 預設為true, 用于啟用優化Apk的操作