Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ data class TrackerEvent(
o.putAll(buildInObject)
o[EVENT] = event
o[TIME] = time
Tracker.projectName?.let { o.put("project_name", it) }
o["mode"] = mode()
o["type"] = "track"

o[LIB] = buildInLib
val properties = HashMap<String, Any>()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.foolchen.lib.tracker.service

import io.reactivex.Observable
import okhttp3.RequestBody
import retrofit2.Response
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.*

/**
* 上报接口的定义
Expand All @@ -18,13 +16,20 @@ interface TrackerAPIDef {
/**
* 上报数据接口
*
* @param path 上报数据的接口地址
* @param projectName 要上报数据的项目名称
* @param data 要上报的JSON数据
* @param mode 上报数据的模式
*/
@FormUrlEncoded
@POST("{url}")
fun report(@Path("url") path: String, @Field("project") projectName: String, @Field(
"data") data: String, @Field("mode") mode: Int): Observable<Response<String>>
fun report(
@Path("url") path: String,
@Field("data_list") data: String
): Observable<Response<String>>

/**
* 上报数据接口
*
* @param data 要上报的JSON数据
*/
@POST("{url}")
fun report(@Path("url") path: String, @Body body: RequestBody): Observable<Response<String>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.RequestBody
import org.jetbrains.anko.db.*
import retrofit2.Response
import retrofit2.Retrofit
Expand Down Expand Up @@ -47,78 +49,68 @@ object TrackerService {
if (Tracker.mode == TrackerMode.RELEASE) {
// 如果为release模式,则此处需要考虑同步、批量上传等处理
// 首先将事件添加到事件列表中
mEvents.add(event)
addEvent(event)
// 然后判断事件数量是否达到了上传的阈值
if (mEvents.size >= threshold() || background || foreground) {
// 如果达到了阈值,则进行后续操作
val reportEvents = prepareEvents()// 准备要上报的事件
report(reportEvents,
// 在从后台切换到前台时,将反序列化方法当做实参传入,用于将数据库中的事件读取出来
if (foreground) this@TrackerService::deserializeEvents else null,
// 如果当前要统计的事件为切换到后台,则将序列化方法当做实参传递,用于在上报失败后将数据存储到数据库
// 否则,将恢复事件方法当做实参传递,在上报失败后,将数据再次添加到候选列表中
if (background) this@TrackerService::serializeEvents else this@TrackerService::addEvents)
// 在从后台切换到前台时,将反序列化方法当做实参传入,用于将数据库中的事件读取出来
if (foreground) this@TrackerService::deserializeEvents else null,
// 如果当前要统计的事件为切换到后台,则将序列化方法当做实参传递,用于在上报失败后将数据存储到数据库
// 否则,将恢复事件方法当做实参传递,在上报失败后,将数据再次添加到候选列表中
if (background) this@TrackerService::serializeEvents else this@TrackerService::addEvents)
}
} else if (Tracker.mode == TrackerMode.DEBUG_TRACK) {
// 如果为debug&track模式,则直接上传数据,并且不关注失败
mService.report(Tracker.servicePath!!, Tracker.projectName!!,
prepareReportJson(listOf(event)),
mode()).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe(
IgnoreObserver())
mService.report(Tracker.servicePath!!,
createRequestBody(prepareReportJson(listOf(event)))).subscribeOn(
Schedulers.io()).observeOn(
Schedulers.io()).subscribe(
IgnoreObserver())
}
}

private fun report(events: List<TrackerEvent>, deserializeFunc: KFunction0<List<TrackerEvent>>?,
failureFunc: (List<TrackerEvent>) -> Unit) {
failureFunc: (List<TrackerEvent>) -> Unit) {
Observable
.create<List<TrackerEvent>> {
// 如果传入的反序列化方法不为空,则将反序列化的数据传递到下一步
// 否则,则传递一个空的List
it.onNext(deserializeFunc?.invoke() ?: Collections.emptyList<TrackerEvent>())
it.onComplete()
}
.map {
// 此处,在反序列化数据不为空的情况下,将反序列化数据添加到要上报的数据中
(events as MutableList<TrackerEvent>).addAll(it) // 由于已知此处肯定为ArrayList,故直接进行转换
events
}
.flatMap {
mService.report(Tracker.servicePath!!, Tracker.projectName!!,
prepareReportJson(it), mode())
}
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(object : IgnoreObserver() {
override fun onNext(t: Response<String>) {
super.onNext(t)
if (t.code() == 200) {
// 接口请求成功
// 则此时不做任何处理
} else {
// 接口请求失败
// 则此时将上报失败的事件添加回待上报的事件列表中
failureFunc.invoke(events)
}
}

override fun onError(e: Throwable) {
super.onError(e)
.create<List<TrackerEvent>> {
// 如果传入的反序列化方法不为空,则将反序列化的数据传递到下一步
// 否则,则传递一个空的List
it.onNext(deserializeFunc?.invoke() ?: Collections.emptyList<TrackerEvent>())
it.onComplete()
}
.map {
// 此处,在反序列化数据不为空的情况下,将反序列化数据添加到要上报的数据中
(events as MutableList<TrackerEvent>).addAll(it) // 由于已知此处肯定为ArrayList,故直接进行转换
events
}
.flatMap {
mService.report(Tracker.servicePath!!,
createRequestBody(prepareReportJson(it)))
}
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(object : IgnoreObserver() {
override fun onNext(t: Response<String>) {
super.onNext(t)
if (t.code() == 200) {
// 接口请求成功
// 则此时不做任何处理
} else {
// 接口请求失败
// 则此时将上报失败的事件添加回待上报的事件列表中
failureFunc.invoke(events)
}
})
}
}

/** 根据枚举类型来计算上报接口时使用的模式 */
private fun mode(): Int {
return when (Tracker.mode) {
TrackerMode.DEBUG_ONLY -> 1
TrackerMode.DEBUG_TRACK -> 2
else -> {
3
}
}
override fun onError(e: Throwable) {
super.onError(e)
// 接口请求失败
// 则此时将上报失败的事件添加回待上报的事件列表中
failureFunc.invoke(events)
}
})
}

/** 根据当前的上报模式计算触发上报的阈值 */
Expand Down Expand Up @@ -151,6 +143,13 @@ object TrackerService {
mEvents.sortBy { it.time }
}

/** 将一批事件添加到事件列表中,该操作为同步操作 */
@Synchronized
private fun addEvent(event: TrackerEvent) {
mEvents.add(event)
// 在添加到列表中后,根据时间对所有的时间进行排序
mEvents.sortBy { it.time }
}

/** 准备上传使用的JSON数据 */
private fun prepareReportJson(events: List<TrackerEvent>): String {
Expand All @@ -166,14 +165,17 @@ object TrackerService {
return json
}

private fun createRequestBody(s: String) = RequestBody.create(MediaType.parse("text/plain"),
"data_list=$s")

/** 对事件列表进行持久化 */
private fun serializeEvents(events: List<TrackerEvent>) {
Tracker.trackContext.getApplicationContext().let {
Tracker.trackContext?.getApplicationContext()?.let {
it.database.use {
transaction {
events.forEach {
insert(EventContract.TABLE_NAME, EventContract.DATA to GSON.toJson(it),
EventContract.TIME to it.time)
EventContract.TIME to it.time)
}
}
}
Expand All @@ -183,19 +185,19 @@ object TrackerService {
/** 对事件列表进行反持久化 */
private fun deserializeEvents(): List<TrackerEvent> {
val events = ArrayList<TrackerEvent>()
Tracker.trackContext.getApplicationContext().database.use {
Tracker.trackContext?.getApplicationContext()?.database?.use {
// 查找出所有的数据
select(EventContract.TABLE_NAME, EventContract.DATA).orderBy(EventContract.TIME,
SqlOrderDirection.ASC)
.exec {
val deserializeEvents = parseList(object : RowParser<TrackerEvent> {
override fun parseRow(columns: Array<Any?>): TrackerEvent {
val data = columns[0] as String
return GSON.fromJson(data, TrackerEvent::class.java)
}
})
events.addAll(deserializeEvents)
}
SqlOrderDirection.ASC)
.exec {
val deserializeEvents = parseList(object : RowParser<TrackerEvent> {
override fun parseRow(columns: Array<Any?>): TrackerEvent {
val data = columns[0] as String
return GSON.fromJson(data, TrackerEvent::class.java)
}
})
events.addAll(deserializeEvents)
}
// 然后将所有的数据从数据库中删除
delete(EventContract.TABLE_NAME)
}
Expand All @@ -220,19 +222,19 @@ object TrackerService {
builder.baseUrl(Tracker.serviceHost!!)
builder.client(createOkHttpClient())
mRetrofit = builder
.addConverterFactory(ToStringConverterFactory())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.addConverterFactory(ToStringConverterFactory())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
}
}
return mRetrofit!!
}

private fun createOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder().connectTimeout(Tracker.timeoutDuration,
TimeUnit.MILLISECONDS)
.readTimeout(Tracker.timeoutDuration, TimeUnit.MILLISECONDS)
.writeTimeout(Tracker.timeoutDuration, TimeUnit.MILLISECONDS).build()
TimeUnit.MILLISECONDS)
.readTimeout(Tracker.timeoutDuration, TimeUnit.MILLISECONDS)
.writeTimeout(Tracker.timeoutDuration, TimeUnit.MILLISECONDS).build()
}

/** [Observer]的实现类,默认实现忽略所有回调。如有需要可覆写对应方法 */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ internal fun Fragment.getTrackProperties(): Map<String, Any> {
return properties
}

@Suppress("UNUSED_PARAMETER")
internal fun View.getTrackProperties(ev: MotionEvent?): Map<String, Any> {
// 首先获取元素本身的属性
val properties = HashMap<String, Any>()
Expand All @@ -115,6 +114,17 @@ internal fun View.getTrackProperties(ev: MotionEvent?): Map<String, Any> {
return properties
}

/** 根据枚举类型来计算上报接口时使用的模式 */
internal fun mode(): Int {
return when (Tracker.mode) {
TrackerMode.DEBUG_ONLY -> 1
TrackerMode.DEBUG_TRACK -> 2
else -> {
3
}
}
}

/**
* 对事件进行统计
*
Expand All @@ -123,7 +133,7 @@ internal fun View.getTrackProperties(ev: MotionEvent?): Map<String, Any> {
* @param foreground 当前事件是否为切换到前台
*/
internal fun trackEvent(event: TrackerEvent, background: Boolean = false,
foreground: Boolean = false) {
foreground: Boolean = false) {
// 此处尝试对数据进行上报
// 具体的上报策略由TrackerService掌控
TrackerService.report(event, background, foreground)
Expand Down