這是博主第一次sdk開發(fā)工作,是開發(fā)過程中的感悟和心得,寫得不好,還請指正
公司背景是一家專門從事sdk開發(fā)服務的公司,這次樓主接到sdk開發(fā)的任務,項目經(jīng)理告知說可以依靠之前公司的sdk進行修修改改就可以完成任務,樓主就這么做了,可是做到后期項目需求變化發(fā)現(xiàn)公司之前的sdk根本不能用了,但是項目也進行了一大半,所有就在之前的代碼框架下完成,到項目后期功能全部完成后,才發(fā)現(xiàn)有大問題;
sdk框架前期沒有經(jīng)過合理的設計,導致sdk內部許多代碼邏輯會暴露給客戶,暴露了sdk的安全問題,所有在次提醒,在進行開發(fā)之前一定要做好框架的設計,一個好的框架也就標志著一個好的項目
項目功能都開發(fā)完了,時間也緊迫,博主為了補救項目的缺失,把代碼內部的邏輯能修理的盡量修理了,最后實在不能掩藏,就進行代碼混淆和將代碼寫入到jni里面去,這樣解決后,雖然不能保證能完全解決問題,但是還是從一定程度上為代碼加了一道安全鎖
以下是在開發(fā)過程中遇到問題時的感悟
代碼框架設計
樓主認為框架設計的目的是:
- 將整個項目合理的拆分為許多模塊,各個模塊功能職責明確,降低各個模塊的依賴,耦合;做到想用某一個模塊時就用,不用時就去除掉,并且不影響其他模塊
- 合理設計類與類之間的繼承關系,接口的實現(xiàn)關系,和利用java的public、private、protected、default權限,來掩藏代碼內部邏輯,爭取做到只暴露外部開發(fā)接口,完全掩藏內部邏輯
樓主認為:
以功能為單位劃分模塊,無論功能大小均劃分成模塊,方便后期代碼升級可以進行添加;
模塊設計準則:
a. 模塊設計準則:在一個功能模塊下,放于同一個package下,根據(jù)功能點為這個模塊創(chuàng)建一個接口,創(chuàng)建兩個功能管理類并實現(xiàn)前面的該接口,一個用于對外部模塊開放接口,另一個用于控制模塊內部邏輯。最后,在將模塊內部真正實現(xiàn)的代碼邏輯類全部設置為default權限,保證package以外的無法訪問;如下圖:

b. 類與類的繼承、接口實現(xiàn);如果有多個相同的功能的代碼塊,都為其寫一個基類,子類來繼承即可;接口方面,如果多個類有相同的功能,但實現(xiàn)不一樣則就用接口來實現(xiàn)(ps這塊了解的不多,有高見還請賜教)
其他的安全、代碼冗余等問題也是老生常談的問題,也需要去合理設計
總結下來也就是面向對象設計的幾大原則:
- 優(yōu)化代碼的第一步 —— 單一職責原則
- 讓程序更穩(wěn)定、更靈活 —— 開閉原則
- 構建擴展性更好的系統(tǒng) —— 里氏替換原則
- 讓項目擁有變化的能力 —— 依賴倒置原則
- 系統(tǒng)有更高的靈活性 —— 接口隔離原則
- 更好的可擴展性 —— 迪米特原則
jni操作
內部算法類,數(shù)據(jù)加解密已一些數(shù)據(jù)操作的類,盡量都寫在jni內,這樣代碼的安全性會大大增加。jni操作見這兒eclipse jni基礎操作和Android studio jni基礎操作
代碼混淆
在某些內部類無法掩藏的前提下或者你想保護它不被別人看到,可以使用代碼混淆來保護;
代碼混淆主要是通過修改類名、成員名和方法名等,并且在內部建立了一張映射表,使破解者不容易看懂代碼而已,記住只是不易而已
混淆方法:
主要是在proguard-android文件下編寫混淆代碼,當你打開混淆時,默認是所有代碼均進行混淆,你編寫的代碼就是保持哪些類不被混淆,一般來說下面幾個你不能混淆
不能混淆的地方
- 你引用的第三方庫不能混淆
- 系統(tǒng)的api,如一些activity的生命周期方法不能混淆
- 在androidmainfest里面的activity不能混淆
- 你需要暴露的接口不能混淆
混淆語法
-keep 某一個class
-keep public class * extends Android.app.Activity //這個類不能保持不混淆
-keep public class * extends Android.app.Activity{*;} //類以及里面的成員方法都不混淆
-keep public class com.jack.xinyounative.bean.**{*;} //這個路徑下的類以及成員不混淆
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod //注解 異常 內部類等不混淆
#jar config
-dontwarn okhttp3.** //不能有告警
-keep class okhttp3.**{*;}
-keep public class com.jack.xinyounative.bean.OrderInfo{
public void setSubject(java.lang.String);
public void setBody(java.lang.String);
public void setAmount(int);
public void setApp_user_name(java.lang.String);
public void setNotify_url(java.lang.String);
public void setApp_order_id(java.lang.String);
public void setApp_user_id(java.lang.String);
public void setExt(java.lang.String);
} //類里面的某些方法不能混淆
-keepclasseswithmembers class **.R$*{
public static <fields>;
} //資源文件不能混淆
由于Android studio默認是release混淆,所以你需要在gradle里面修改為debug或者增加release的混淆代碼,如下:
buildTypes {
debug{
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
最后,如果你還想加密apk的,不妨嘗試修改apk的arsc文件,修改文件頭即可,讓apktool失效;更或者給apk加殼,使別人看到的代碼只是殼而已,等等等....
到這一步,大體都已經(jīng)完成了,如果哪位仁兄有更好的建議,還忘不吝賜教