Skip to content

Commit

Permalink
ADD Read and write batchId
Browse files Browse the repository at this point in the history
  • Loading branch information
ninovanhooff committed Jun 27, 2022
1 parent d0e8508 commit 934d3f5
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 53 deletions.
89 changes: 56 additions & 33 deletions q42stats/src/main/java/com/q42/q42stats/library/HttpService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package com.q42.q42stats.library

import androidx.annotation.WorkerThread
import org.json.JSONObject
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
Expand All @@ -11,47 +13,68 @@ import javax.net.ssl.HttpsURLConnection
@WorkerThread
internal object HttpService {

fun sendStatsSync(config: Q42StatsConfig, data: JSONObject) {
/** Sends stats and returns body as String if successful */
fun sendStatsSync(config: Q42StatsConfig, data: JSONObject, lastBatchId: String?): JSONObject? =
httpPost(
"https://q42stats.ew.r.appspot.com/add/${config.firestoreCollectionId}",
data,
config.apiKey
)
}
config.apiKey,
lastBatchId
)?.let { JSONObject(it) }
}

private fun httpPost(url: String, jsonObject: JSONObject, apiKey: String) {
val conn = URL(url).openConnection() as HttpsURLConnection
try {
conn.requestMethod = "POST"
conn.setRequestProperty("Connection", "close")
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8")
// Explicitly tell the server to not gzip the response.
// Otherwise, HttpUrlsConnection will open a GzipInflater and not close it,
// which triggers a StrictMode violation
// https://issuetracker.google.com/issues/37069164#comment11
conn.setRequestProperty("Accept-Encoding", "identity")
conn.setRequestProperty("X-Api-Key", apiKey)
sendPostRequestContent(conn, jsonObject)
} catch (e: Throwable) {
Q42StatsLogger.e(TAG, "Could not send stats to server", e)
} finally {
conn.disconnect()
private fun httpPost(
url: String,
jsonObject: JSONObject,
apiKey: String,
lastBatchId: String?
): String? {
val conn = URL(url).openConnection() as HttpsURLConnection
try {
conn.requestMethod = "POST"
conn.setRequestProperty("Connection", "close")
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8")
// Explicitly tell the server to not gzip the response.
// Otherwise, HttpUrlsConnection will open a GzipInflater and not close it,
// which triggers a StrictMode violation
// https://issuetracker.google.com/issues/37069164#comment11
conn.setRequestProperty("Accept-Encoding", "identity")
conn.setRequestProperty("X-Api-Key", apiKey)
lastBatchId?.let {
conn.setRequestProperty("batchId", it)
}
return sendPostRequestContent(conn, jsonObject)
} catch (e: Throwable) {
Q42StatsLogger.e(TAG, "Could not send stats to server", e)
} finally {
conn.disconnect()
}

private fun sendPostRequestContent(conn: HttpURLConnection, jsonObject: JSONObject) {
try {
conn.outputStream.use { os ->
BufferedWriter(OutputStreamWriter(os, "UTF-8")).use { writer ->
writer.write(jsonObject.toString())
Q42StatsLogger.d(TAG, "Sending JSON: $jsonObject")
writer.flush()
}
return null
}

private fun sendPostRequestContent(conn: HttpURLConnection, jsonObject: JSONObject): String? {
try {
conn.outputStream.use { os ->
BufferedWriter(OutputStreamWriter(os, "UTF-8")).use { writer ->
writer.write(jsonObject.toString())
Q42StatsLogger.d(TAG, "Sending JSON: $jsonObject")
writer.flush()
}
// Only when reading the response, the request gets executed
Q42StatsLogger.d(TAG, "Response: ${conn.responseCode} ${conn.responseMessage}")
} catch (e: Throwable) {
Q42StatsLogger.e(TAG, "Could not add data to POST request", e)
}
// Only when reading the response, the request gets executed
Q42StatsLogger.d(TAG, "Response: ${conn.responseCode} ${conn.responseMessage}")
if (conn.responseCode in 200..299) {
return conn.getResponseText()
}
} catch (e: Throwable) {
Q42StatsLogger.e(TAG, "Could not add data to POST request", e)
}
return null
}

private fun HttpURLConnection.getResponseText(): String {
BufferedReader(InputStreamReader(inputStream)).use {
return it.readText()
}
}
15 changes: 10 additions & 5 deletions q42stats/src/main/java/com/q42/q42stats/library/Q42Stats.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,20 @@ class Q42Stats(private val config: Q42StatsConfig) {
val payload: Map<String, Any> = mapOf<String, Any?>(
"Stats Version" to "Android ${BuildConfig.LIB_BUILD_DATE}",
"currentMeasurement" to currentMeasurement,
"previousMeasurement" to prefs.previousMeasurement
"previousMeasurement" to prefs.previousMeasurement,
).filterValueNotNull()
HttpService.sendStatsSync(
val responseBody = HttpService.sendStatsSync(
config,
payload.toQ42StatsApiFormat()
payload.toQ42StatsApiFormat(),
prefs.lastBatchId
)
responseBody?.let {
val batchId = it.getString("batchId") // throws if not found
prefs.lastBatchId = batchId
prefs.previousMeasurement = currentMeasurement
prefs.updateSubmitTimestamp()
}

prefs.previousMeasurement = currentMeasurement
prefs.updateSubmitTimestamp()
} catch (e: Throwable) {
handleException(e)
} finally {
Expand Down
27 changes: 12 additions & 15 deletions q42stats/src/main/java/com/q42/q42stats/library/Q42StatsPrefs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import android.content.Context
import android.content.SharedPreferences
import org.json.JSONArray
import org.json.JSONObject
import java.util.*

private const val SHARED_PREFS_NAME = "Q42StatsPrefs"
private const val LAST_SUBMIT_TIMESTAMP_KEY = "lastSubmitTimestamp"
private const val PREVIOUS_MEASUREMENT_KEY = "previousMeasurement"
private const val LAST_BATCH_ID_KEY = "lastBatchId"

internal class Q42StatsPrefs(context: Context) {
private val prefs: SharedPreferences =
Expand All @@ -27,10 +28,16 @@ internal class Q42StatsPrefs(context: Context) {
apply()
}

fun getOrCreateInstallationId(): String {
val uuid = prefs.getString(INSTALLATION_ID_KEY, null)
return uuid ?: createInstallationId()
}
var lastBatchId: String?
get() = prefs.getString(LAST_BATCH_ID_KEY, null)
set(value) = with(prefs.edit()) {
value?.let {
putString(LAST_BATCH_ID_KEY, it)
} ?: run {
remove(LAST_BATCH_ID_KEY)
}
apply()
}

fun withinSubmitInterval(interval: Long) =
System.currentTimeMillis() <
Expand All @@ -41,13 +48,6 @@ internal class Q42StatsPrefs(context: Context) {
apply()
}

private fun createInstallationId(): String = with(prefs.edit()) {
val uuid = UUID.randomUUID().toString()
putString(INSTALLATION_ID_KEY, uuid)
apply()
return uuid
}

private fun JSONObject.toMap(): Map<String, Any?> = keys().asSequence().associateWith {
when (val value = this[it]) {
is JSONArray -> {
Expand All @@ -61,6 +61,3 @@ internal class Q42StatsPrefs(context: Context) {
}

}

private const val INSTALLATION_ID_KEY = "installationId"
private const val PREVIOUS_MEASUREMENT_KEY = "previousMeasurement"

0 comments on commit 934d3f5

Please sign in to comment.