Android studio 使用心得(五)---程式碼混淆和破解apk
這篇文章等是跟大家分享一在Android studio 進行程式碼混淆配置。之前大家在eclipse上也弄過程式碼混淆配置,其實一樣,大家可以把之前在eclipse上的配置檔案直接拿過來用。不管是.cfg檔案還是proguard-rules.pro檔案都一樣。
先給大家貼一個混淆模板吧。註釋很清楚。是我目前一個專案用的proguard.cfg配置檔案
#指定程式碼的壓縮級別 -optimizationpasses5 #包明不混合大小寫 -dontusemixedcaseclassnames #不去忽略非公共的庫類 -dontskipnonpubliclibraryclasses #優化 不優化輸入的類檔案 -dontoptimize #預校驗 -dontpreverify #混淆時是否記錄日誌 -verbose # 混淆時所採用的演算法 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #保護註解 -keepattributes *Annotation* # 保持哪些類不被混淆 -keeppublicclass* extendsandroid.app.Fragment -keeppublicclass* extendsandroid.app.Activity -keeppublicclass* extendsandroid.app.Application -keeppublicclass* extendsandroid.app.Service -keeppublicclass* extendsandroid.content.BroadcastReceiver -keeppublicclass* extendsandroid.content.ContentProvider -keeppublicclass* extendsandroid.app.backup.BackupAgentHelper -keeppublicclass* extendsandroid.preference.Preference -keeppublicclasscom.android.vending.licensing.ILicensingService #如果有引用v4包可以新增下面這行 -keeppublicclass* extendsandroid.support.v4.app.Fragment #忽略警告 -ignorewarning #####################記錄生成的日誌資料,gradle build時在本專案根目錄輸出################ #apk 包內所有 class的內部結構 -dumpclass_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 掉 -keepclasscom.nostra13.universalimageloader.** { *; } #友盟 -keepclasscom.umeng.**{*;} #支付寶 -keepclasscom.alipay.android.app.IAliPay{*;} -keepclasscom.alipay.android.app.IAlixPay{*;} -keepclasscom.alipay.android.app.IRemoteServiceCallback{*;} -keepclasscom.alipay.android.app.lib.ResourceMap{*;} #信鴿推送 -keepclasscom.tencent.android.tpush.** {* ;} -keepclasscom.tencent.mid.** {* ;} #自己專案特殊處理程式碼 #忽略警告 -dontwarn com.veidy.mobile.common.** #保留一個完整的包 -keepclasscom.veidy.mobile.common.** { *; } -keepclass com.veidy.activity.login.WebLoginActivity{*;} -keepclass com.veidy.activity.UserInfoFragment{*;} -keepclass com.veidy.activity.HomeFragmentActivity{*;} -keepclass com.veidy.activity.CityActivity{*;} -keepclass com.veidy.activity.ClinikActivity{*;} #如果引用了v4或者v7包 -dontwarn android.support.** ############<span></span>混淆保護自己專案的部分程式碼以及引用的第三方jar包library-end################## -keeppublicclass* extendsandroid.view.View { public<init>(android.content.Context); public<init>(android.content.Context, android.util.AttributeSet); public<init>(android.content.Context, android.util.AttributeSet, int); publicvoidset*(...); } #保持 native 方法不被混淆 -keepclasseswithmembernamesclass* { native <methods>; } #保持自定義控制元件類不被混淆 -keepclasseswithmembersclass* { public<init>(android.content.Context, android.util.AttributeSet); } #保持自定義控制元件類不被混淆 -keepclasseswithmembersclass* { public<init>(android.content.Context, android.util.AttributeSet, int); } #保持自定義控制元件類不被混淆 -keepclassmembersclass*extendsandroid.app.Activity { publicvoid*(android.view.View); } #保持 Parcelable 不被混淆 -keepclass*implementsandroid.os.Parcelable { publicstaticfinal android.os.Parcelable$Creator *; } #保持 Serializable 不被混淆 -keepnamesclass*implementsjava.io.Serializable #保持 Serializable 不被混淆並且enum 類也不被混淆 -keepclassmembersclass*implementsjava.io.Serializable { staticfinallongserialVersionUID; privatestaticfinal java.io.ObjectStreamField[] serialPersistentFields; !static!transient <fields>; !private<fields><span></span>; !private<methods>; privatevoidwriteObject(java.io.ObjectOutputStream); privatevoidreadObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); } #保持列舉 enum 類不被混淆 如果混淆報錯,建議直接使用上面的 -keepclassmembers class*implementsjava.io.Serializable即可 #-keepclassmembers enum * { # publicstatic**[] values(); # publicstatic** valueOf(java.lang.String); #} -keepclassmembersclass* { publicvoid*ButtonClicked(android.view.View); } #不混淆資源類 -keepclassmembersclass**.R$* { publicstatic<fields>; } #避免混淆泛型 如果混淆報錯建議關掉 #–keepattributes Signature #移除log 測試了下沒有用還是建議自己定義一個開關控制是否輸出日誌 #-assumenosideeffectsclassandroid.util.Log { # publicstaticboolean isLoggable(java.lang.String, int); # publicstaticint v(...); # publicstaticint i(...); # publicstaticint w(...); # publicstaticint d(...); # publicstaticint e(...); #}
另外加上一段,如果用用到Gson解析包的,直接新增下面這幾行就能成功混淆,不然會報錯。
#gson
#-libraryjars libs/gson-2.2.2.jar
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }
如果你使用了webview
# webview + js
-keepattributes *JavascriptInterface*
# keep 使用 webview 的類
-keepclassmembersclass com.veidy.activity.WebViewActivity {
public*;
}
# keep 使用 webview 的類的所有的內部類
-keepclassmembers class com.veidy.activity.WebViewActivity$*{
*;
}
?
大家可以先看看這篇文章
瞭解一下打包過程。
然後大家看看打包的配置檔案build.gradle裡面的一段配置程式碼
一切就緒後,就是打包了。這裡我就不再多說了,大家可以去看
我這裡用第二種,gradle 命令打包.我建議大家在gradle clean後,不要直接gradle build,而是用gradleassembleRelease .用gradle build第一是因為慢,第二,我自己專案打包時這樣遇到一個錯誤,現在也沒解決
Lint found errors in the project; aborting build.
Fix the issues identified by lint, or add the following to your build script to proceed with errors:
...
android {
lintOptions {
abortOnError false
}
}
...
可以我明明已經設定
//執行lint檢查,有任何的錯誤或者警告提示,都會終止構建,我們可以將其關掉。
lintOptions {
abortOnError false
}
搞不清楚。希望大家誰知道的也告訴下我。
當我們執行命令 gradle build或者gradleassembleRelease後,會自動進行混淆操作。。。直到成功。
各位 注意下,如果你的混淆配置有問題,可能會報錯。Execution failed for task ':proguardUmengRelease'.大家可以根據報錯去排除問題,
比如說我遇到的一個問題,
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
} 大家可以看到這個錯誤提示,有一個line 168 ,這個是行號,但是各位注意了這個行號定位不是特別精準,只能一個大概的定位。 混淆真正的成功與否,需要我們自己來親自驗證,那就是我們來破解自己的apk.我上傳了 一個我使用的破解工具 連結: http://pan.baidu.com/s/1o60tLj0 密碼: 3bqp 1,解壓apk.用好壓就能直接解壓,獲取到classes.dex檔案 2.用dex2jar這個工具來生成classes_dex2jar檔案. a,把剛剛解壓出來的classes.dex檔案放到dex2jar根目錄,然後用dos命令定位到該目錄,執行命令dex2jar.bat classes.dex直到done. 2.細心的朋友就會發現多了一個jar檔案。 . c.然後用jd-gui開啟這個jar檔案,就能看到專案的結構了。。 如果有a.b.c這些,就說明混淆成功啦