conventionschedule-android/app/src/main/java/com/adlerosn/brasilfurfest/schedule/managers/UpdateChecker.kt

84 lines
3.9 KiB
Kotlin

package com.adlerosn.brasilfurfest.schedule.managers
import android.content.Context
import com.adlerosn.brasilfurfest.helper.lastPathPart
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import java.io.Serializable
import java.lang.IllegalStateException
import java.net.HttpURLConnection
import java.net.HttpURLConnection.HTTP_NOT_MODIFIED
import java.net.HttpURLConnection.HTTP_OK
import java.net.URL
class UpdateChecker(context: Context): Serializable {
val cacheManager = CacheManager(context).also { it.startMonitoringNeededFiles() }
private val baseJsonFileName = RemoteAssets.json.lastPathPart()
val hasBaseJsonCached get() = baseJsonFileName.let {
cacheManager.getStamp(it) != null
}
fun downloadBaseJsonWithWatcher(watcher: (DownloadState, ByteArray?, Throwable?)->Any?) =
downloadWithWatcher(RemoteAssets.json, watcher)
fun downloadWithWatcher(httpThingToFetch: String, watcher: (DownloadState, ByteArray?, Throwable?)->Any?) =
if(cacheManager.goesOnline)
doAsync {
try {
val url = URL(httpThingToFetch)
val diskIdentifier = url.toString().lastPathPart()
val connection = url.openConnection() as HttpURLConnection
cacheManager.getStamp(diskIdentifier)?.let {
connection.setRequestProperty("If-Modified-Since", it)
}
connection.useCaches = false
connection.connectTimeout = 3000
connection.readTimeout = 5000
connection.allowUserInteraction = false
connection.doOutput = false
connection.requestMethod = "GET"
uiThread { watcher(DownloadState.CONNECTING, null, null) }
connection.connect()
try {
val resCode = connection.responseCode
when (resCode) {
HTTP_OK -> {
uiThread { watcher(DownloadState.CACHE_MISS, null, null) }
val lastModified = connection.headerFields["last-modified"]?.firstOrNull()
val data = connection.inputStream.buffered().readBytes()
cacheManager[diskIdentifier] = Pair(data, lastModified ?: "")
uiThread { watcher(DownloadState.SUCCESS, data, null) }
}
HTTP_NOT_MODIFIED -> {
uiThread { watcher(DownloadState.CACHE_HIT, null, null) }
val bytes = cacheManager[diskIdentifier]?.first?.readBytes()
uiThread { watcher(DownloadState.SUCCESS, bytes, null) }
}
else -> {
throw IllegalStateException("Server replied with code $resCode. Expected either $HTTP_OK or $HTTP_NOT_MODIFIED.")
}
}
} catch (t: Throwable) {
uiThread { watcher(DownloadState.ERROR, null, t) }
} finally {
connection.disconnect()
}
} catch (t: Throwable) {
uiThread { watcher(DownloadState.ERROR, null, t) }
}
}
else
doAsync { uiThread {
watcher(DownloadState.CONNECTING, null, null)
watcher(DownloadState.CACHE_HIT, null, null)
watcher(DownloadState.SUCCESS, cacheManager[httpThingToFetch.lastPathPart()]!!.first.readBytes(), null)
} }
enum class DownloadState{
CONNECTING,
CACHE_MISS,
CACHE_HIT,
ERROR,
SUCCESS
}
}