from://http://blog.csdn.net/musicvs/article/details/7948627
代碼混淆與反射的沖突
反編譯Android的代碼,大部分人都知道了,防反編譯的方法也大部分都知道了(盡管它不一定一直有效,但起碼像我這種水平的人,沒辦法看到混淆之后的Java代碼, 最可惡的是沒有注釋= =)。
最近才發現,我的代碼在很久之后設置了混淆,也在很久之前不知道什么時候不小心把代碼混淆給弄沒了(好吧,你可以去反編譯我的項目了,我不介意,因為代碼很爛,實在是爛)。
於是,這兩個又在搞混淆代碼了,混淆代碼的方法很簡單:
1.在項目下新建一個文件,命名為“proguard.cfg”,正常情況下包括以下內容:
-optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -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 <methods>; } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } |
2.然后編輯項目下的“project.properties”文件,在最后加上一句:proguard.config=proguard.cfg
OK,大功告成,記住了,只有打包的時候代碼才會混淆,直接運行項目然后去bin目錄下找的那個apk包是不會混淆的。
這么簡單的事情,當然就不會特意來這分享了~
我想說說我遇到的問題,那就是,當代碼混淆遇上Java反射時,一堆麻煩來了。
==============別睡着了啊,真正的問題來了============
是的,我們會發現,Java的反射再也找不到它想找的類,或者方法,或者屬性了。
是的,因為代碼混淆的原因,原本的類名、方法名、屬性名都改變了,而反射它還是按照原來的名字去反射,結果只能射出一個程序崩潰。
解決的方法當然有~
那就是,讓和反射有關的那些代碼或者類,不進行混淆,那就不會有上述的問題了~!
再看看proguard.cfg文件,里面那么多代碼,不可能沒有用的,來,先隨便整一句看看:
-keep public class * extends android.app.Activity |
很簡單的,這句話的意思是,保留所有繼承Activity的類,不進行混淆。來,馬上舉一反三:
-keep public class com.mutou.test.HelloWorld |
這句更加簡單了,保留HelloWorld,不進行混淆。
注意了,所有的類必須指出完整的包路徑(廢話了,這個文件里又沒有import語句,當然要完整路徑了,不然它哪知道那個類在哪兒~)。
不進行混淆的意思就是,當我們的android項目的代碼被反編譯工具反編譯出來之后,代碼看起來不會像天書一樣,不會所有變量名、方法名都變成a、b、c、d什么的。
又注意了,有一個比較糾結的地方,一定要小心,通過上面兩種方式防止混淆的代碼,並不代表,反編譯之后和源碼一模一樣,它的類名什么的都和源碼一樣,但是變量名、方法名就不一定了,它也有可能是abcd什么的。這個我也不知道為嘛。總之,小心就是了。
也正因為如此,在有反射的代碼里(吶,別問我什么叫做反射啊,我只是要用的時候百度了一下,現在已經忘了具體用法了),不能通過以上兩種方式來防止代碼混淆。
==============真正的主題在不華麗的分割線下面============
那,沒有辦法了嗎?
有啊~木了個頭的,沒有辦法我就不來發帖了~~
嘻嘻,看看:
-keepclasseswithmembernames class com.kogame.god.thing.creature.** { *; } |
糟糕~這個有點復雜,別着急~
先看看這個名字:keepclasseswithmembernames 顧名思義,就是保留類以及它的成員的名字。
那花括號里面那個”*;”又是什么東西呢?它代表類里的所有成員(包括變量、方法)的名字都不會被混淆,都保留原汁原味的樣子。
於是,整段代碼的意思就是,保留所有繼承creature類的代碼以及它的變量和方法,不進行混淆。
好喇~~
謝謝觀賞。
如果沒有聽懂的,請移步(更簡單明了詳細而不復雜的文章):
http://www.apkbus.com/android-57338-1-1.html