由于Android的代碼大都是Java代碼,所以挺容易被反編譯的,好在Android ADT為我們集成了混淆代碼的工具,一來可以混淆我們的代碼,讓程序被反編譯后基本看不懂,另外還能起到代碼優(yōu)化的作用。發(fā)布項目前,建議打開Android的代碼混淆功能。
創(chuàng)新互聯(lián)專注于宜春企業(yè)網(wǎng)站建設,成都響應式網(wǎng)站建設,購物商城網(wǎng)站建設。宜春網(wǎng)站建設公司,為宜春等地區(qū)提供建站服務。全流程專業(yè)公司,專業(yè)設計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務
Android ADT主要通過ProGuard工具來提供代碼混淆,網(wǎng)上也有挺多博客文章講這個的,但感覺很多都介紹得太過于復雜,這里我就以問答的方式來更加簡潔地介紹下ProGuard吧。
1. ProGuard是什么
ProGuard是一個工具,用來混淆和優(yōu)化Java代碼。
工作方式:移除無效的代碼,將代碼中的類名、函數(shù)名替換為晦澀難懂的名字。
注意,它只能混淆Java代碼,Android工程中Native代碼,資源文件(圖片、xml),它是無法混淆的。
2. 如何開啟ProGuard
修改Android工程根目錄下的project.properties文件,把proguard.config=....這一行前面的注釋“#”去掉。
這一行指定了系統(tǒng)默認的proguard配置文件,位于Android SDK/tools/proguard目錄下。
當然,你也可以自己編寫配置文件,但不建議這樣做,因此系統(tǒng)默認的配置已經(jīng)涵蓋了許多通用的細節(jié),如果你還有額外的配置,可以添加在 proguard-project.txt 文件中。
注意: 只有在生成release版本的apk時,混淆配置才會起作用,debug版本的apk不會進行混淆。
3. 哪些內(nèi)容需要手動配置
系統(tǒng)默認的配置已經(jīng)涵蓋了大部分的內(nèi)容,但是如果你的工程中有如下內(nèi)容,則需要手動添加配置到proguard-project.txt文件中。
(1) 只在 AndroidManifest.xml 引用的類
(2) 通過JNI回調(diào)方式被調(diào)用的函數(shù)
(3) 運行時動態(tài)調(diào)用的函數(shù)或者成員變量
(4) 當然,如果你不確定哪些需要手動配置,可以以默認的配置生成程序,當運行中發(fā)現(xiàn)ClassNotFoundException異常時,即可找到哪個類不該被混淆。
4. 手動配置的規(guī)則
手動添加的配置,一般以“-keep”開頭,常用的配置命令分別示例如下:
假設Android工程中有一個接口和一個類:
package com.ticktick.example; public interface TestInterface { public void test(); } public class Test { private String mTestString; private final int mMinValue; private final int mMaxValue; public Test( int min, int max){ mMinValue = min; mMaxValue = max; } public int getMinValue() { return mMinValue; } public int getMaxValue() { return mMaxValue; } public void setTestString(String testStr ) { mTestString = testStr; } }
(1) 不混淆某個類的構(gòu)造函數(shù)
例如:不混淆Test類的構(gòu)造函數(shù):
-keepclassmembers class com.ticktick.example.Test { public(int,int); }
(2) 不混淆某個包所有的類或指定的類
例如,不混淆package com.ticktick.example下的所有類/接口
-keep class com.ticktick.example.** { * ; }
例如,不混淆com.ticktick.example.Test類:
-keep class com.ticktick.example.Test { * ; }
如果希望不混淆某個接口,則把上述命令中的class替換為interface即可。
(3) 不混淆某個類的特定的函數(shù)
例如:不混淆com.ticktick.example.Test類的setTestString函數(shù):
-keepclassmembers class com.ticktick.example.Test { public void setTestString(java.lang.String); }
(4) 不混淆某個類的子類,某個接口的實現(xiàn)
例如:不混淆com.ticktick.example.Test類的子類
-keep public class * extends com.ticktick.example.Test
例如:不混淆com.ticktick.example.TestInterface的實現(xiàn)
-keep class * implementscom.ticktick.example.TestInterface { public static final com.ticktick.example.TestInterface$Creator *; }
(5) 添加第三方依賴包
例如:添加android-support-v4.jar依賴包
-libraryjars libs/android-support-v4.jar -dontwarn android.support.v4.**{*;} -keep class android.support.v4.**{*;} -keep interface android.support.v4.**{*;}
注意: 需要添加dontwarn,因為默認情況下proguard會檢查每一個引用是否正確,但是第三方庫里往往有些不會用到的類,沒有正確引用,所以如果不配置的話,系統(tǒng)會報錯。
5. 混淆后的調(diào)試信息解析
當代碼混淆之后,輸出的Log信息也會帶有混淆內(nèi)容,比如函數(shù)名和類名會被替換為晦澀難懂的名字,而與代碼中的不一致。
因此,ProGuard工具還提供了恢復混淆內(nèi)容的工具和文件。
當你開啟了ProGuard混淆后,每次生成release版的apk時,Andriod工程的根目錄下會對應生成一個proguard文件夾,該文件夾下的mapping.txt文件記錄了混淆后的名字與混淆前的名字的對應關系,通過該文件,我們反向得到恢復后的Log信息。
假設Log文件名為log.txt,則恢復混淆的命令為:
$retrace.sh -verbose mapping.txt log.txt
注1:retrace.sh命令位于
注2:你需要保存每一個release版本的mapping.txt,因為每一次release的混淆結(jié)果和映射關系都不一樣。
關于Android的代碼混淆我就總結(jié)到這兒了,你也可以去ProGuard的官方網(wǎng)頁上獲取關于ProGuard更加詳細的介紹,有任何疑問歡迎留言或者來信lujun.hust@gmail.com交流,或者關注我的新浪微博 @盧_俊 獲取最新的文章和資訊。