这是博主第一次sdk开发工作,是开发过程中的感悟和心得,写得不好,还请指正
公司背景是一家专门从事sdk开发服务的公司,这次楼主接到sdk开发的任务,项目经理告知说可以依靠之前公司的sdk进行修修改改就可以完成任务,楼主就这么做了,可是做到后期项目需求变化发现公司之前的sdk根本不能用了,但是项目也进行了一大半,所有就在之前的代码框架下完成,到项目后期功能全部完成后,才发现有大问题;
sdk框架前期没有经过合理的设计,导致sdk内部许多代码逻辑会暴露给客户,暴露了sdk的安全问题,所有在次提醒,在进行开发之前一定要做好框架的设计,一个好的框架也就标志着一个好的项目
项目功能都开发完了,时间也紧迫,博主为了补救项目的缺失,把代码内部的逻辑能修理的尽量修理了,最后实在不能掩藏,就进行代码混淆和将代码写入到jni里面去,这样解决后,虽然不能保证能完全解决问题,但是还是从一定程度上为代码加了一道安全锁
以下是在开发过程中遇到问题时的感悟
代码框架设计
楼主认为框架设计的目的是:
- 将整个项目合理的拆分为许多模块,各个模块功能职责明确,降低各个模块的依赖,耦合;做到想用某一个模块时就用,不用时就去除掉,并且不影响其他模块
- 合理设计类与类之间的继承关系,接口的实现关系,和利用java的public、private、protected、default权限,来掩藏代码内部逻辑,争取做到只暴露外部开发接口,完全掩藏内部逻辑
楼主认为:
以功能为单位划分模块,无论功能大小均划分成模块,方便后期代码升级可以进行添加;
模块设计准则:
a. 模块设计准则:在一个功能模块下,放于同一个package下,根据功能点为这个模块创建一个接口,创建两个功能管理类并实现前面的该接口,一个用于对外部模块开放接口,另一个用于控制模块内部逻辑。最后,在将模块内部真正实现的代码逻辑类全部设置为default权限,保证package以外的无法访问;如下图:
![模块设计](http://upload-images.jianshu.io/upload_images/4442190-ef960c0e29c61c03?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
b. 类与类的继承、接口实现;如果有多个相同的功能的代码块,都为其写一个基类,子类来继承即可;接口方面,如果多个类有相同的功能,但实现不一样则就用接口来实现(ps这块了解的不多,有高见还请赐教)
其他的安全、代码冗余等问题也是老生常谈的问题,也需要去合理设计
总结下来也就是面向对象设计的几大原则:
- 优化代码的第一步 —— 单一职责原则
- 让程序更稳定、更灵活 —— 开闭原则
- 构建扩展性更好的系统 —— 里氏替换原则
- 让项目拥有变化的能力 —— 依赖倒置原则
- 系统有更高的灵活性 —— 接口隔离原则
- 更好的可扩展性 —— 迪米特原则
jni操作
内部算法类,数据加解密已一些数据操作的类,尽量都写在jni内,这样代码的安全性会大大增加。jni操作见这儿eclipse jni基础操作和Android studio jni基础操作
代码混淆
在某些内部类无法掩藏的前提下或者你想保护它不被别人看到,可以使用代码混淆来保护;
代码混淆主要是通过修改类名、成员名和方法名等,并且在内部建立了一张映射表,使破解者不容易看懂代码而已,记住只是不易而已
混淆方法:
主要是在proguard-android文件下编写混淆代码,当你打开混淆时,默认是所有代码均进行混淆,你编写的代码就是保持哪些类不被混淆,一般来说下面几个你不能混淆
不能混淆的地方
- 你引用的第三方库不能混淆
- 系统的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加壳,使别人看到的代码只是壳而已,等等等....
到这一步,大体都已经完成了,如果哪位仁兄有更好的建议,还忘不吝赐教