一款稳定、易用、安全、小巧灵活的推送SDK是怎么样的?本文将从“小”、“稳”、“好用”以及“安全”四个角度来具体阐述。
对于非技术出身的产品经理来说,如果突然接到一个要“设计SDK”的活儿,其实并不容易。毕竟,SDK是主要面向开发者的,更像一个toD产品。那么,产品经理在设计SDK时,需要注意哪些点呢?换句话说,一款好的SDK应该具备哪些特性?本文将从“小”、“稳”、“好用”以及“安全”四个角度来具体阐述。

如上图(左)所示,程序最终会生成dex文件,dex文件主要由以下几部分组成:header(标头)、一连串的ids(标识符列表)、data(数据区)以及link_data(静态链接文件中使用的数据)。
细看上图(右),它包含了一个method_ids_size字段,该字段的主要作用是定义个数。根据谷歌的定义,uint是一个16位的short类型,最长长度是65535。如果将dex工程反编译,会生成很多smali的文件,再去看smali里的函数调用(比如invoke direct {***} 函数名@BBB),会发现调用的地址其实就是刚才unit里定义的偏移量计算得出的。因此,这个函数地址最多也只能有65535个。
1.2 如何使包体体积变小如何减小包体的体积,建议从以下几个方面考虑:
(1)自研,不嵌套
在设计研发SDK时,不建议在SDK内嵌套一系列框架,例如三方网络框架、db框架或任务调度框架等。我们主张选择最核心的一部分进行自主研发。
(2)代码优化
从算法层面,在效果相同的情况下,可适当减少代码的行数;对于有默认赋值的变量不需要进行初始化赋值;选择合适的字符串拼接方式,建议使用StringBuilder方法拼接字符串,可以解决字符串频繁修改带来的内存消耗,也有利于减少包体体积大小。
(3)追求实用,放弃完美
SDK包体应当追求实用性,以完善主功能为主,其他相对次要的部分可以适当减少时间或精力投入,放弃完美主义思维。
(4)代码混淆
借助代码混淆实现更小体积的包体,且不易被逆向。
1.3 省电省流量省电省流量是“小”的另一个方面。SDK如果没有对流量和电量有严格的限制,否则会出现手机发烫、高耗电提醒、流量浪费、内置SDK APP难以上架等问题。
针对上述问题,我们可以设置通过Lock杀手,智能心跳、自定义协议、链路合并、按需活跃等方式尽可能地降低SDK对电量以及流量造成的消耗。
(1)Lock杀手:代码中WiFiLock、WakeLock等会强制唤醒APP,导致APP产生较大耗电量。在不影响功能的前提下,我们应尽量减少或者不用该类锁。
(2)智能心跳:应根据不同的运营商、网络状态等,选择不同的心跳策略,并且根据不同的应用场景探索心跳的最大边界,尽量延长心跳周期,减少电量和网络的消耗。
(3)自定义协议:市场上常用的json、xml、甚至PB协议,都有比较好的兼容扩展性,但同样也带来了空间浪费的问题,自定义协议可以充分利用空间,精确利用每一个byte甚至bit,极简化封装,承载最大的信息量,减少流量和电量浪费。
(4)链路合并:当一个设备有多个APP的推送链路同时活跃时,我们会运用合并链路技术,将使用同一款SDK的 APP 之间的长连接链路进行合并,减少流量电量的浪费。

SDK设计开发过程中,我们还需要注意安全性。安全性不仅仅代表网络数据交互的安全、本地数据存储的安全,也涉及到 SDK 的加固、混淆、第三方安全软件审核等。
其中,我们重点讲解SDK的加固。目前安卓平台SDK绝大部分都是Java语言编写,容易被反编译。SDK如果只是进行了简单的混淆,很容易被窥探到内部实现细节,此外还可能存在SDK被二次打包、植入恶意广告等现象。因此,我们需要对SDK进行加固,以提升安全性。
如上图所示,SDK的加固主要是Java层面和so层面的操作。Java层面可以进行SSR IR指令转换或者做Java2C处理,把实现细节放入native中;so层面可以做一些扁平化、虚假控制等来混淆代码,也可以通过指令替换、指令跳转逻辑来增加逆向难度。此外,也可以通过常量字符串加密加固SDK,这是目前较为简单实用的一种方式。
现在看来,要设计开发一款好的SDK最难的还是如何让自己设计的SDK在复杂的环境下稳定运行,这需要我们对 SDK 的架构有比较清晰的认知,并不断迭代和优化。
那么以上提到的四点,也是各位产品经理和开发者需要注意的,希望对大家有所帮助。
作者:叶新江,个推CTO
本文由 @个推 原创发布于人人都是产品经理,未经许可,禁止转载。
题图来自 Unsplash,基于 CC0 协议