一个好的消息推送SDK应该具有稳定、易用、安全、小巧灵活等特色。个推做为国内第三方推送市场的早期进入者,一直致力于为开发者提供高效稳定的推送SDK。通过多年的打磨和创新,个推沉淀了丰厚的技术经验。这期文章将从“小”、“稳”、“好用”以及“安全”四个角度分享个推推送SDK的技术经验。算法
好的消息推送SDK首要需考虑到包体的小巧灵活性。为何选择更小体积的包体?从代码层面来看,是因为系统的“65535限制”。如上图(左)所示,咱们的程序最终会生成dex文件,dex文件主要由如下几部分组成:header(标头)、一连串的ids(标识符列表)、data(数据区)以及link_data(静态连接文件中使用的数据)。细看上图(右),它包含了一个method_ids_size字段,该字段的主要做用是定义个数。根据谷歌的定义,uint是一个16位的short类型,最长长度是65535。若是将dex工程反编译,会生成不少smali的文件,再去看smali里的函数调用(好比invoke direct {*} 函数名@BBB),会发现调用的地址其实就是刚才unit里定义的偏移量计算得出的。所以,这个函数地址最多也只能有65535个。json
如何减少包体的体积,能够从如下几个方面考虑:缓存
(1)自研,不嵌套:在研发SDK时,不建议开发者在SDK内嵌套一系列框架,例如三方网络框架、db框架或任务调度框架等。咱们主张开发者选择最核心的一部分进行自主研发。安全
(2)代码优化:从算法层面,在效果相同的状况下,可适当减小代码的行数;对于有默认赋值的变量不须要进行初始化赋值;选择合适的字符串拼接方式,建议使用StringBuilder方法拼接字符串,能够解决字符串频繁修改带来的内存消耗,也有利于减小包体体积大小。网络
(3)追求实用,放弃完美:SDK包体应当追求实用性,以完善主功能为主,其余相对次要的部分能够适当减小时间或精力投入,放弃完美主义思惟。架构
(4)代码混淆:借助代码混淆实现更小体积的包体,且不易被逆向。并发
省电省流量是“小”的另外一个方面。做为一款好的消息推送SDK,应该对流量和电量有严格的限制,不然会出现手机发烫、高耗电提醒、流量浪费、内置SDK APP难以上架等问题。针对上述问题,咱们能够经过Lock杀手,智能心跳、自定义协议、链路合并、按需活跃等方式尽量地下降SDK对电量以及流量形成的消耗。框架
(1)Lock杀手:代码中WiFiLock、WakeLock等会强制唤醒APP,致使APP产生较大耗电量。在不影响功能的前提下,咱们应尽可能减小或者不用该类锁。ide
(2)智能心跳:应根据不一样的运营商、网络状态等,选择不一样的心跳策略,而且根据不一样的应用场景探索心跳的最大边界,尽可能延长心跳周期,减小电量和网络的消耗。模块化
(3)自定义协议:市场上经常使用的json、xml、甚至PB协议,都有比较好的兼容扩展性,但一样也带来了空间浪费的问题,自定义协议能够充分利用空间,精确利用每个byte甚至bit,极简化封装,承载最大的信息量,减小流量和电量浪费。
(4)链路合并:当一个设备有多个APP的推送链路同时活跃时,咱们会运用合并链路技术,将使用“个推 SDK”的 APP 之间的长链接链路进行合并,减小流量电量的浪费。
在实际应用中,开发者可能会遇到ANR、OOM、Crash、内存泄露、闪退等棘手的问题,为了打造好的消息推送SDK,咱们须要经过持续的迭代和优化来将错误最小化。
(1)作好代码管理:除了借助SVN、GIT等工具作好代码托管外,开发者还需遵循必定的代码规范,借助相似gerrit等工具进行代码review,使用verify流程。在保证机器找不到问题的前提下,再用人眼去辨别是否符合业务逻辑。
(2)自动化测试:自动化测试能够大幅提高回归测试的效率,很是适合敏捷的开发过程。此外,自动化测试能够替代大量的手工机械重复性操做,测试工程师能够把更多的时间花在更全面的用例设计和新功能测试上。
(3)运用代码模块化等小技巧:代码模块化能以最少的模块、零部件,更快速地知足更多的个性化需求。异常处理能够提升系统的容错性,让程序更加稳定。代码检测能及时发现程序中的缺陷和错误,好比检测内存是否泄露,是否有安全漏洞等,保证代码质量。
(4)线上灰度:实际场景中,咱们很难去覆盖全部的环境,例如机型、网络等,须要经过线上用户的反馈去验证代码的健壮性。所以在产品大规模推向用户以前,咱们须要进行少许的真实用户测试,即灰度上线来帮助减小风险。
(5)日志系统:系统有问题是必然的,在尽可能保持系统稳定的前提下,要考虑容错性。当问题发生时,须要第一时间以最快的速度排查,所以须要有一套完整的日志系统。此外,平时咱们也能够经过日志系统的拨测检测系统的健壮性,能够在用户反馈以前及时发现并解决问题。
兼容性也是保证好的消息推送SDK稳定性的一个重要条件,主要考虑如下几个方面:
(1)接口兼容:每次版本更新后,对外接口要尽量保持不变。对于改动较大的接口,可使用 @Deprecated 注解对老接口进行标记,而且作新接口调用的兼容,而不是直接删除老接口。
(2)主键兼容:当主键发生变动(例如去掉service、provider)时,部分老的安卓系统会有组件缓存,运行时直接告知“类”找不到。建议在AndroidManifest中保留声明,且对应“类”进行代码空实现,以减小发生crash的几率。
(3)安卓系统兼容:可以使用Build.VERSION.SDK_INT作API区分。
(4)真机兼容:能够借助云测等平台进行兼容性测试。
SDK的易用性能够从下面几个方面考虑:
(1)接入简单:接入SDK时有集成demo直接能够运行,且接入文档清晰、步骤简单,最好能实现一键集成。
(2)保持核心优点:一款好的消息推送SDK,咱们主要考虑及时性、到达率、稳定性和准确性。例如,新闻媒体类APP对推送的及时性要求较高;通知类推送(如转帐信息)会特别注重消息的到达率;稳定性指的是要保证推送SDK在不一样环境下的正常运行,尤为是11.11等高并发场景;准确性主要针对广告营销类推送,须要在合适的时间、合适的地点和合适的场景把合适的内容推送给合适的人。其中,关于如何保证稳定性,能够从多线路、多IDC、热备份等角度考虑。① 多线路调整:例如预埋三线域名,作一些轮询策略,防止域名被劫持。② 多IDC设置:除了域名被劫持外,还可能遇到网络攻击,物理性损坏的状况。设置多IDC一方面是为了实现分流,另外一方面也下降了风险。③ 热备份:系统处于正常运转状态下的备份,一旦系统出现问题,能够快速恢复。
(3)多样化需求:经过丰富的画像标签,对用户进行场景化的智能推送,知足用户的多样化需求。
(4)策略可控:咱们还提供静默时间、推送控量、短信补量、定时展现等附加功能,知足客户的实际使用场景。
$4 安全
SDK开发过程当中,咱们还须要注意安全性。安全性不只仅表明网络数据交互的安全、本地数据存储的安全,也涉及到 SDK 的加固、混淆、第三方安全软件审核等。
其中,咱们重点讲解SDK的加固。目前安卓平台SDK绝大部分都是Java语言编写,容易被反编译。SDK若是只是进行了简单的混淆,很容易被窥探到内部实现细节,此外还可能存在SDK被二次打包、植入恶意广告等现象。所以,咱们须要对SDK进行加固,以提高安全性。
如上图所示,SDK的加固主要是Java层面和so层面的操做。Java层面能够进行SSR IR指令转换或者作Java2C处理,把实现细节放入native中;so层面能够作一些扁平化、虚假控制等来混淆代码,也能够经过指令替换、指令跳转逻辑来增长逆向难度。此外,也能够经过常量字符串加密加固SDK,这是目前较为简单实用的一种方式。
总结来讲,其实开发一款好的消息推送SDK并不难,难的是如何让本身开发的SDK在复杂的环境下稳定运行,这须要咱们对 SDK 的架构有比较清晰的认知,并不断迭代和优化。但愿本文能为各位开发者在实际操做中提供必定帮助,个推也会不断打磨技术、持续创新,与各位开发者一同分享关于推送以及其余领域的最新思路及方法。