乐趣区

关于前端:神策分析-Android-SDK-网络模块解析

前言

在信息化时代,数据成为挪动互联网企业的贵重资源。数据的获取、上报、贮存、剖析乃至可视化地出现,都成为了以后重要的钻研方向。当然,大数据分析最外围的还是数据,其中数据的起源更是至关重要的。如何保证数据可能精确、及时、残缺地上传到指定的服务端,是神策剖析 Android SDK 须要面临的外围问题。

神策剖析 Android SDK 针对数据传输,从完整性、正确性以及高效性等多方面综合思考,设计并实现了一套实用于数据采集的网络传输计划。上面针对神策剖析 Android SDK 网络模块进行具体的介绍,心愿可能给大家提供一些参考。

网络申请计划

大多数 App 都会和服务端进行交互,因而须要连贯到网络能力失常应用。数据采集 SDK 须要将数据上传到指定的服务端,同样须要依赖网络。Android 中网络申请的实现有多种形式,例如:能够应用一些比拟成熟的网络框架,疾速实现网络申请性能;或者应用 Android 零碎提供的网络拜访 API 实现网络申请性能。上面别离介绍这两种计划的优缺点。

基于开源网络框架

Android 中有很多优良的开源网络框架,例如:Volley、OkHttp、Retrofit + RxJava、NoHttp 等,基于开源网络框架能够方便快捷地实现网络申请性能。

基于开源网络框架实现有如下长处:

能够缩小代码量,将重点放在业务上,不须要在技术框架上消耗过多的工夫;
功能丰富,应用门槛低;
风行的开源网络框架通过泛滥利用的验证,性能绝对稳固。
然而,基于开源网络框架实现也有一些毛病:

性能较多,代码逻辑简单,学习老本较高;
外部缺点修复难度大甚至须要依赖作者来更新保护;
蕴含很多可能应用不到的性能以及冗余的代码,引入后会导致体积增大很多。
基于开源网络框架实现网络申请计划有利有弊,能够依据理论须要抉择适合的开源网络框架。

基于零碎办法

基于零碎办法实现的网络申请计划通常采纳 HttpURLConnection 或 HttpClient:

HttpURLConnection:在 JDK 的 http://java.net 包提供的一种多用途、轻量级的拜访 HTTP 协定的基本功能类,大多数的应用程序都应用该接口进行网络拜访申请;
HttpClient:是 Apache 开源组织提供的网络拜访类,封装了 HTTP 协定的细节实现,Android 6.0 之前蕴含在零碎 API 中。
它们都提供较多的 API,而且绝对比较稳定。这两种网络申请类均有以下性能:

反对 HTTPS 协定网络申请;
能够配置超时工夫;
反对 IPv6 协定;
反对连接池;
能够实现流媒体的上传与下载。
在 Android 6.0 之前大多数利用的网络申请是通过 HttpClient 实现的,相比拟于 HttpURLConnection,应用 HttpClient 具备以下劣势:

从易用性方面比照:HttpClient 封装了 HTTP 协定的细节,应用起来比拟不便。HttpURLConnection 是 Java 的规范类,因为短少封装导致应用不便;
从稳定性方面比照:HttpClient 功能强大且更稳固,容易管制细节。而之前的 HttpURLConnection 始终存在着版本兼容的问题。
从 Android 6.0 开始移除了 HttpClient,如果在 Android 6.0 以上持续应用 HttpClient 时,须要在相应的 module 下的 build.gradle 中进行依赖库配置。具体配置如下:

android {useLibrary ‘org.apache.http.legacy’}

因而,在 Android 6.0 以上更举荐应用 HttpURLConnection。从上述的剖析能够看出:之前始终应用 HttpClient 是因为 HttpURLConnection 不稳固导致的。目前谷歌曾经修复了 HttpURLConnection 存在的一些问题,相比 HttpClient 劣势如表 2-1 所示:

表 2-1 HttpURLConnection 与 HttpClient 性能比照

因而,应用基于零碎办法实现的网络申请计划个别采纳 HttpURLConnection 来实现。

SDK 网络模块

如果 SDK 网络模块基于开源网络框架实现,可维护性和版本控制都有肯定的危险,此外还会导致 SDK 体积增大很多。因为这些毛病很难被用户所承受,因而基于开源网络框架实现网络模块不适用于 SDK。

思考到上述起因,SDK 网络模块最终采纳了基于 HttpURLConnection 的形式实现。HttpURLConnection 是零碎提供的网络拜访 API,不仅可满足 SDK 网络申请的须要,而且零碎 API 性能更稳固,更易扩大。

原理介绍

实现原理

Android 中进行网络申请是基于 HTTP 协定实现的。HTTP 协定是目前 Internet 上最常应用、最重要的协定,该协定为典型的申请 – 响应模型:

客户端建设连贯并发送申请;
服务端承受并解决申请;
服务端发送应答;
客户端承受并解决应答。
在基于 HttpURLConnection 实现网络申请计划时,很有必要对 HttpURLConnection 有进一步的理解。HttpURLConnection 继承自 URLConnection 抽象类,URLConnection 类自身依赖于 Socket 类实现网络连接。Socket 又称做套接字,它把简单的网络操作形象为简略的接口供下层调用。因为 HttpURLConnection 并不是底层的连贯,而是在底层连贯上的一个申请,因而 HttpURLConnection 不须要设置 Socket。

HttpURLConnection 反对 GET、POST、PUT、DELETE 等申请形式,最罕用的就是 GET 与 POST 申请,上面从数据传输长度和安全性两方面比照:

数据传输长度:一般来说,GET 申请传输的数据长度有限度(URL 有长度限度),POST 申请传输的数据长度没有限度;
安全性:GET 申请安全性较差(发送的数据会拼接在 URL 前面),POST 申请绝对平安(数据不显示在 URL 中)。
思考到 SDK 采集的数据量绝对较大,且对数据安全性要求较高,因而采纳 HttpURLConnection POST 形式实现网络申请。

应用形式
HttpURLConnection 的具体应用步骤如图 3-1 所示:

图 3-1 HttpURLConnection 应用流程

因为波及到网络拜访,须要在 Manifest 文件中增加网络拜访权限:

<uses-permission android:name=”android.permission.INTERNET”/>

以上是对 HttpURLConnection 的原理以及具体应用的介绍,上面对 SDK 中网络申请的具体实现进行介绍。

具体实现

网络相干配置

SDK 能够对数据上报进行一系列的配置,开发者可依据 App 的特点设置相应的配置,从而达到最高效的数据上报成果。SDK 的相干配置在初始化时实现,能够配置的参数如下:

mServerUrl:数据上报地址,采集的本地数据将上报到该地址;
mFlushInterval:两次数据发送的最小工夫距离(单位毫秒),默认值为 15;
mFlushBulkSize:本地缓存数据的最大条目数,当本地缓存条数达到 mFlushBulkSize 则会上报数据,默认值为 100;
mNetworkTypePolicy:网络上传策略,可配置为 3G、4G、5G、WIFI 等网络类型进行上报。
工作线程封装
SDK 数据上报是在子线程中实现的,当采集的数据满足上报策略时触发数据异步上报,上传工作的治理调度在 Worker 类中实现。在 Worker 初始化时,创立 HandlerThread 实例,HandlerThread 实质上是一个线程类,它继承自 Thread 类。HandlerThread 内有本人的 Looper 对象,能够进行 Looper 循环。通过获取 HandlerThread 中 Looper 对象传递给 Handler 对象,能够在 handleMessage 办法中执行异步工作。

AnalyticsMessageHandler 继承自 Handler,在 handleMessage 中接管 Worker 发送的音讯并执行数据上报或删除。HandlerThread 中的 Looper 对象传递给 AnalyticsMessageHandler 对象,在 handleMessage 办法中实现异步网络工作。AnalyticsMessageHandler 代码实现如下:

private class AnalyticsMessageHandler extends Handler {…… Worker() {final HandlerThread thread = new HandlerThread(“com.sensorsdata.analytics.android.sdk.AnalyticsMessages.Worker”, Thread.MIN_PRIORITY); thread.start(); mHandler = new AnalyticsMessageHandler(thread.getLooper()); } @Override public void handleMessage(Message msg) {…… if (msg.what == FLUSH_QUEUE) {sendData(); } else if (msg.what == DELETE_ALL) {try { mDbAdapter.deleteAllEvents(); } catch (Exception e) {com.sensorsdata.analytics.android.sdk.SALog.printStackTrace(e); } } else {SALog.i(TAG, “Unexpected message received by SensorsData worker: ” + msg); } …… } ……}

Worker 中封装了 runMessage 和 runMessageOnce 两个办法:runMessage 办法用于执行数据实时上报;runMessageOnce 办法用于延时执行上报工作。通过 Handler 中的 sendMessageDelayed() 办法即可实现数据的延时上报。

数据上报策略

在 SDK 数据存储解析中介绍了数据的采集与存储策略:采集的数据会先保留到本地,合乎上报策略才会上报。

客户端本地存储的数据超过肯定条数时(默认 100 条)会上报数据
在 SDK 初始化时,可配置 mFlushBulkSize 参数来管制条数限度。如果不进行设置,则默认为 100 条。如果用户设置的条数小于 50 条,则默认为 50 条。SDK 采集的数据较多,如果设置上报条数太小会导致频繁的网络申请(上报数据),从而影响性能。如果用户设置上报条数过多,会导致一次上传的数据过大,这样不仅会导致上传工夫长还很可能会呈现上传失败的状况。如果没有特殊要求,可间接应用默认值。

数据采集后距离肯定工夫(默认 15 秒)会上报数据
在 SDK 初始化时,可配置 mFlushInterval 参数来管制工夫距离限度。如果不满足上报条数限度时,SDK 会执行一个延时工作,延时 mFlushInterval 设定的工夫后执行。

除了上文中提到的策略外,还会在触发以下事件时,会以阻塞的模式将本地缓存的数据全副上报:

在采集 $AppEnd 事件时上报数据;
捕捉 App 异样时上报数据;
在激活事件触发后上报数据。

数据安全

数据加密

SDK 上报的数据波及到用户隐衷,爱护用户隐衷是开发者应尽的责任和任务。SDK 提供数据加密策略对上报的数据进行加密,以避免用户信息在传输过程中产生透露。

SDK 的数据加密策略是将采集到的数据缓存到本地,而后采纳 RSA + AES 加密算法进行加密,次要实现流程如下:

App 内置 RSA 公钥及密钥(假如为 A),或者从服务端获取(从服务端获取不便更换公钥,毛病是应用更多的传输带宽、减少初始化的老本;另外服务端同时应用多个密钥对,解密时须要选取对应私钥,若密钥过多可能会影响导入性能);
随机生成长度为 128 位的对称加密 AES 对称秘钥(假如为 B),应用 RSA 公钥 A 对 AES 对称密钥 B 进行加密;
用户触发事件产生 JSON 数据,应用 AES 对称秘钥 B 对采集的事件(即整条 JSON 数据)进行加密产生密文数据;
依照与后盾约定的格局拼装数据存储到本地。
拼装后的格局如下:

{“pkv”: RSA 公钥对应的秘钥编号, “ekey”: “ 应用 RSA 公钥 A 对 AES 对称密钥 B 加密产生的密文 ”, “payload”: “ 应用 AES 对称秘钥 B 对采集的事件即整条 JSON 数据进行加密产生密文数据 ”}

上报数据时,会从磁盘读取数据。依据加密计划,ekey 字段会很长(与 RSA 密钥长度无关),每条带一个 ekey 冗余较多。因而,在上报之前会进行数据合并,对于“ekey”雷同的数据,合并到一个数组中。合并后发送到服务端的数据格式如下:

[{“pkv”: RSA 公钥对应的秘钥编号 1, “ekey”: “ 应用 RSA 公钥 A 对 AES 对称密钥 B 加密产生的密文 ”, “payloads”: [“加密后的事件数据 1”,“加密后的事件数据 2”]},{“pkv”: RSA 公钥对应的秘钥编号 2, “ekey”: “ 应用 RSA 公钥 A 对 AES 对称密钥 B 加密产生的密文 ”, “payloads”: [“加密后的事件数据 3”,“加密后的事件数据 4”]}]

最初,服务端应用“pkv”对应的私钥解密“ekey”字段失去 AES 对称密钥的参数 key,解密 payloads 失去多条音讯原文。

HTTPS 双向验证
HTTPS 是在 HTTP 上建设的 SSL 加密层,并对传输数据进行加密,是 HTTP 协定的平安版。

在 HTTP 协定中可能存在平安问题,次要包含以下几个方面:

传输的数据应用明文,可能被窃取;
无奈校验数据是否残缺;
无奈确认通信单方的身份。
应用 HTTPS 协定能够无效地避免这些问题:

内容通过加密并生成一个惟一的加密秘钥;
可能校验数据是否残缺;
能够确认通信单方的身份。
SDK 反对 HTTPS 协定网络申请,通过 HTTPS 双向验证保证数据的安全性。

数据上报流程

数据采集时,会创立一个异步工作退出到工作队列中,通过 TrackTaskManagerThread 调度工作程序执行。在子线程中执行一个工作时,首先采集预置属性信息,其次将预置信息和自定义属性信息封装成神策须要的 JSON 格局,存储到数据库中。

如果以后处于 Debug 模式或者数据库超过最大缓存限度时,会进行上报数据操作;不满足时会进行如下判断:如果触发的事件为“$SignUp”或者本地缓存的条数大于设置的 mFlushBulkSize 时会进行上报数据;否则会触发延时上报,在距离设置的 mFlushInterval 工夫上报数据。上报流程如图 3-2 所示:

图 3-2 数据上报流程图

发送数据时,以下状况不会发送数据:

用户设置 mEnableNetworkRequest 为 false 时不会上报数据,用户可通过 enableNetworkRequest 办法设置是否上报数据;
serverURL 为空时不会上报数据;
不在主过程时不会上报数据;
无网络时不会上报数据;
不满足 SDK 设置的上报策略时不会上报数据。
满足上报条件时,SDK 会将本地的数据全副上报。如果一次传输的数据较大,会减少数据上传失败的可能性,同时对性能的影响也比拟大。因而,SDK 一次最多读取 50 条数据,对读取的原始事件数据先采纳 Gzip 压缩,而后对压缩的内容进行 Base64 编码,保障高效的传输。同时思考到数据的完整性和安全性,会将原始数据的 hashCode 值传到服务端,用于对数据完整性校验。

数据上报后,依据网络申请状态码判断数据是否上报胜利:网络申请状态码在 200 ~ 300 之间时,认为 SDK 上报数据是胜利的,会删除本地上报胜利的数据。网络申请失败时,本地数据不删除。每次发送都会循环读取本地缓存的数据,直到数据全副上传实现。

数据上报校验

开发者在集成 SDK 开发过程中,须要校验 SDK 是否将数据失常、精确地上报到服务端。SDK 提供了通过查看 Logcat 控制台日志和 Debug 实时查问的形式来校验数据上报的准确性。

Logcat 本地日志校验

通过日志查看数据是否上报胜利,首先须要在初始化 SDK 后调用 enableLog(true) 关上 SDK 的日志输入性能。如果相应事件触发,SDK 会主动进行采集并定时发送到神策剖析后盾。能够通过 Logcat 查看日志进行数据校验,在 Logcat 中筛选“SA.”可查看事件采集上报的相干日志,具体分为以下几种状况:

埋点事件触发胜利时,输入“track event”结尾的事件数据;
埋点事件触发失败时,输入相应的谬误起因;
事件数据上报胜利时,输入“valid message”字段结尾的事件数据;
事件数据上报失败时,输入“invalid message”字段结尾的事件数据并输入谬误起因。
开发过程中通过日志即可判断数据是否失常上报。

Debug 实时数据查问

SDK 提供了 Debug 模式上报数据性能,不便开发者在集成 SDK 时校验数据。Debug 模式下 SDK 采集的数据会实时进行上报,SDK 提供了 DEBUG_ONLY 和 DEBUG_AND_TRACK 两种模式:

DEBUG_ONLY:采集数据上报到服务端但不会入库,能够在 Debug 实时查问中看到上报的数据,防止在测试过程中产生的脏数据入库;
DEBUG_AND_TRACK:会实时上报数据,同时数据也会入库。
Debug 实时数据查问是在神策剖析零碎中查看数据是否失常上报。应用 Debug 模式须要依据文档正确配置 scheme,Android 中的 scheme 是一种页面内跳转协定。定义本人的 scheme 后,能够实现通过链接拉起利用或者跳转利用中的某个页面。

SDK 中配置 scheme 的目标就是通过扫码拉起利用作为开启 Debug 调试模式的入口。应用办法是:

先应用调试设施扫描网页二维码,开启该设施的「调试模式」;
点击开始刷新后,操作 App 触发事件;
事件上传胜利就会在 Debug 实时数据查看中看到对应的事件。
总结
本文次要介绍了神策剖析 Android SDK 网络模块的具体实现,SDK 网络申请没有基于开源网络框架来实现,防止了体积的适度减少和代码的冗余。通过对系统类 HttpURLConnection 进行封装,采纳欠缺的上报策略,同时对数据进行压缩、编码、校验等操作,实现了数据及时、精确、高性能的上报。

最初,心愿通过这篇文章,大家可能对神策剖析 Android SDK 网络模块有一个零碎的理解。

参考文献

HttpURLConnection 用法解析

Android 摸索之 HttpURLConnection 网络申请

文章起源:公众号神策技术社区

退出移动版