Android Studio相關博客:
Android Studio(二):快捷鍵設置、插件安裝
最近終於把項目做完了,天天加班,累成狗了。 而昨日又忽聞慕和網絡CEO吳波猝然離世的消息,深感互聯網行業在高薪(其實好多人並不高薪哇)的同時,也是高壓力高風險的啊,也在此希望廣大同行可以珍惜生命,遠離代碼,啊呸,是遠離加班熬夜!
好啦,繼續今天的話題,當項目做完之後,作爲一個稱職的開發者,接下來任務自然是打包測試發佈了。
而打包之前,你必須要混淆你的代碼,前提是你不希望別人看到你的代碼!
如果你不混淆你的代碼,會有怎樣的後果呢?知道不?
通過反編譯你的apk文件,你的源代碼和資源文件都將暴漏無疑,就像光着屁股在別人眼瞎亂晃一樣,我覺得它們一定不好受。 作爲一手造就它的你來說,怎麼能讓它不好受呢?
嘿,說到這裏,我想有些初學的開發者已經會有所好奇了:如何反編譯apk文件擦查看源碼呢?再此,給大家推薦兩篇博客,很精簡很易懂《android 代碼 混淆- 原來如此簡單》和 《 Android APK反編譯就這麼簡單 詳解》; 相信你看完這兩篇博客(能跟着做一遍更佳),一定會覺得蛋疼: 尼瑪老子辛辛苦苦搞了幾個月的項目,你幾分鐘就把源碼給我搞到了,當我開源的啊!
好啦,知道不去混淆代碼會有怎樣的影響之後,那我們來看看如何在Android Studio上混淆你的工程代碼吧。
代碼混淆
首先,在你的工程目錄下,找到proguard-rules.pro文件,它就是你要進行編寫混淆配置的文件:
光編寫該文件還不夠哦,你還需要在你module的build.gradle文件中引用該混淆文件:
好了,知道在哪配置混淆文件後,下面開始講講如何配置混淆:
混淆文件 proguard-rules.pro 參數詳解:
-optimizationpasses 5 # 指定代碼的壓縮級別
-dontusemixedcaseclassnames # 是否使用大小寫混合
-dontskipnonpubliclibraryclasses # 是否混淆第三方jar
-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 *;
}
以上是最基礎的配置,幾乎每個項目都需要進行這些地方的混淆(或保持不混淆)。
如果你仔細看過上方的註釋,就會了解一些基本代碼混淆策略了。
只是,這還遠遠不夠,因爲你在項目中,總會不可避免的引用第三方的library庫或是jar包,那,如果你不能夠正確的混淆第三方的資源,可能會導致你的應用無法使用。(我就因爲忘了配置Gson相關的混淆,導致頁面一直沒有數據顯示,蛋疼的一筆)。
貼出我項目中關於第三方的混淆部分:
#如果有引用v4包可以添加下面這行
-keep class android.support.v4.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment
#如果引用了v4或者v7包,可以忽略警告,因爲用不到android.support
-dontwarn android.support.**
#保持自定義組件不被混淆
-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*(...);
}
#保持 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;
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>;
#}
#xUtils(保持註解,及使用註解的Activity不被混淆,不然會影響Activity中你使用註解相關的代碼無法使用)
-keep class * extends java.lang.annotation.Annotation {*;}
-keep class com.otb.designerassist.activity.** {*;}
#自己項目特殊處理代碼(這些地方我使用了Gson類庫和註解,所以不希望被混淆,以免影響程序)
-keep class com.otb.designerassist.entity.** {*;}
-keep class com.otb.designerassist.http.rspdata.** {*;}
-keep class com.otb.designerassist.service.** {*;}
##混淆保護自己項目的部分代碼以及引用的第三方jar包library(想混淆去掉"#")
#-libraryjars libs/umeng-analytics-v5.2.4.jar
#-libraryjars libs/alipaysecsdk.jar
#-libraryjars libs/alipayutdid.jar
#-libraryjars libs/weibosdkcore.jar
# 以libaray的形式引用的圖片加載框架,不想混淆(注意,此處不是jar包形式,想混淆去掉"#")
#-keep class com.nostra13.universalimageloader.** { *; }
###-------- Gson 相關的混淆配置--------
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
###-------- pulltorefresh 相關的混淆配置---------
-dontwarn com.handmark.pulltorefresh.library.**
-keep class com.handmark.pulltorefresh.library.** { *;}
-dontwarn com.handmark.pulltorefresh.library.extras.**
-keep class com.handmark.pulltorefresh.library.extras.** { *;}
-dontwarn com.handmark.pulltorefresh.library.internal.**
-keep class com.handmark.pulltorefresh.library.internal.** { *;}
###--------- reservoir 相關的混淆配置-------
-keep class com.anupcowkur.reservoir.** { *;}
###-------- ShareSDK 相關的混淆配置---------
-keep class cn.sharesdk.** { *; }
-keep class com.sina.sso.** { *; }
###--------------umeng 相關的混淆配置-----------
-keep class com.umeng.** { *; }
-keep class com.umeng.analytics.** { *; }
-keep class com.umeng.common.** { *; }
-keep class com.umeng.newxp.** { *; }
###-----------MPAndroidChart圖庫相關的混淆配置------------
-keep class com.github.mikephil.charting.** { *; }
以上的配置,即是對一個項目的混淆配置了,相對比較完整,大家可以依葫蘆畫瓢,寫更多的配置,對於一些第三方項目的使用,一般官方會給出如何配置混淆,大家需要小心,別忘了配置。
好啦,如果你已經寫好自己的混淆配置文件,不要忘了在build.gradle文件中再次配置下,打開混淆文件:
signingConfigs {
assist {
keyAlias 'assist.keystore'
keyPassword 'assist2017'
storeFile file('../assist.keystore')
storePassword 'assist2017'
}
}
buildTypes {
debug {
// 顯示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
versionNameSuffix "-debug"
minifyEnabled false
zipAlignEnabled false
shrinkResources false
signingConfig signingConfigs.assist
}
release {
// 不顯示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
//混淆
minifyEnabled true
//Zipalign優化
zipAlignEnabled true
// 移除無用的resource文件
shrinkResources true
//加載默認混淆配置文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//簽名
signingConfig signingConfigs.assist
}
}
release節點下,minifyEnabled設置爲true。
導出APK文件
學會了如何混淆你的項目代碼之後,接下來,我們看下,如何使用Android Studio導出APK文件吧。
(1)Android Studio菜單Build->Generate Signed APK
(2)彈出簽名選擇、創建窗口
(3)創建密鑰庫及密鑰,創建後會自動選擇剛創建的密鑰庫和密鑰(已擁有密鑰庫跳過)
點擊“Create new...”按鈕創建密鑰庫
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後的“...”按鈕,選擇或者創建一個密鑰
(5)點擊“Next”按鈕,選擇保存路徑後,點擊“Finish”按鈕完成
(全章結束)