forked from geode-sdk/android-launcher
switch to okio official coroutines
This commit is contained in:
3 files changed
+61
-45
No files matched your search
@@ -100,8 +100,11 @@ dependencies {
|
|||||||
implementation ("androidx.activity:activity-ktx:1.12.3")
|
implementation ("androidx.activity:activity-ktx:1.12.3")
|
||||||
implementation ("androidx.appcompat:appcompat:1.7.1")
|
implementation ("androidx.appcompat:appcompat:1.7.1")
|
||||||
implementation ("androidx.documentfile:documentfile:1.1.0")
|
implementation ("androidx.documentfile:documentfile:1.1.0")
|
||||||
|
|
||||||
implementation ("com.squareup.okio:okio:3.16.4")
|
implementation ("com.squareup.okio:okio:3.16.4")
|
||||||
implementation ("com.squareup.okhttp3:okhttp:5.3.2")
|
implementation ("com.squareup.okhttp3:okhttp:5.3.2")
|
||||||
|
implementation ("com.squareup.okhttp3:okhttp-coroutines:5.3.2")
|
||||||
|
|
||||||
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0")
|
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0")
|
||||||
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.10.0")
|
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.10.0")
|
||||||
implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
|
implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.geode.launcher.updater
|
package com.geode.launcher.updater
|
||||||
|
|
||||||
import com.geode.launcher.utils.DownloadUtils.executeCoroutine
|
|
||||||
import kotlin.time.Clock
|
import kotlin.time.Clock
|
||||||
import kotlinx.datetime.DateTimeUnit
|
import kotlinx.datetime.DateTimeUnit
|
||||||
import kotlin.time.Instant
|
import kotlin.time.Instant
|
||||||
@@ -12,6 +11,7 @@ import kotlinx.serialization.json.okio.decodeFromBufferedSource
|
|||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
import okhttp3.coroutines.executeAsync
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
@@ -62,9 +62,9 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
val call = httpClient.newCall(request)
|
val call = httpClient.newCall(request)
|
||||||
val response = call.executeCoroutine()
|
|
||||||
|
|
||||||
return when (response.code) {
|
return call.executeAsync().use { response ->
|
||||||
|
when (response.code) {
|
||||||
200 -> {
|
200 -> {
|
||||||
val format = Json {
|
val format = Json {
|
||||||
namingStrategy = JsonNamingStrategy.SnakeCase
|
namingStrategy = JsonNamingStrategy.SnakeCase
|
||||||
@@ -72,7 +72,7 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val release = format.decodeFromBufferedSource<List<Release>>(
|
val release = format.decodeFromBufferedSource<List<Release>>(
|
||||||
response.body!!.source()
|
response.body.source()
|
||||||
)
|
)
|
||||||
|
|
||||||
(release.find { it.tagName != "nightly" })
|
(release.find { it.tagName != "nightly" })
|
||||||
@@ -94,7 +94,7 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
throw IOException(msg)
|
throw IOException(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
throw IOException("response 403: ${response.body!!.string()}")
|
throw IOException("response 403: ${response.body.string()}")
|
||||||
}
|
}
|
||||||
404 -> {
|
404 -> {
|
||||||
null
|
null
|
||||||
@@ -104,6 +104,7 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalTime::class)
|
@OptIn(ExperimentalTime::class)
|
||||||
private fun generateRateLimitMessage(resetTime: Instant): String {
|
private fun generateRateLimitMessage(resetTime: Instant): String {
|
||||||
@@ -124,9 +125,8 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
val call = httpClient.newCall(request)
|
val call = httpClient.newCall(request)
|
||||||
val response = call.executeCoroutine()
|
return call.executeAsync().use { response ->
|
||||||
|
when (response.code) {
|
||||||
return when (response.code) {
|
|
||||||
200 -> {
|
200 -> {
|
||||||
val format = Json {
|
val format = Json {
|
||||||
namingStrategy = JsonNamingStrategy.SnakeCase
|
namingStrategy = JsonNamingStrategy.SnakeCase
|
||||||
@@ -134,7 +134,7 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val release = format.decodeFromBufferedSource<Release>(
|
val release = format.decodeFromBufferedSource<Release>(
|
||||||
response.body!!.source()
|
response.body.source()
|
||||||
)
|
)
|
||||||
|
|
||||||
release
|
release
|
||||||
@@ -155,7 +155,7 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
throw IOException(msg)
|
throw IOException(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
throw IOException("response 403: ${response.body!!.string()}")
|
throw IOException("response 403: ${response.body.string()}")
|
||||||
}
|
}
|
||||||
404 -> {
|
404 -> {
|
||||||
null
|
null
|
||||||
@@ -165,6 +165,7 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
suspend fun getLatestIndexRelease(gd: Long, prerelease: Boolean = false): DownloadableLoaderRelease? {
|
suspend fun getLatestIndexRelease(gd: Long, prerelease: Boolean = false): DownloadableLoaderRelease? {
|
||||||
@@ -181,9 +182,8 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
val call = httpClient.newCall(request)
|
val call = httpClient.newCall(request)
|
||||||
val response = call.executeCoroutine()
|
return call.executeAsync().use { response ->
|
||||||
|
when (response.code) {
|
||||||
return when (response.code) {
|
|
||||||
200 -> {
|
200 -> {
|
||||||
val format = Json {
|
val format = Json {
|
||||||
namingStrategy = JsonNamingStrategy.SnakeCase
|
namingStrategy = JsonNamingStrategy.SnakeCase
|
||||||
@@ -191,7 +191,7 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val body = format.decodeFromBufferedSource<LoaderPayload<LoaderVersion>>(
|
val body = format.decodeFromBufferedSource<LoaderPayload<LoaderVersion>>(
|
||||||
response.body!!.source()
|
response.body.source()
|
||||||
)
|
)
|
||||||
|
|
||||||
val release = body.payload ?: throw IOException("index error: ${body.error}")
|
val release = body.payload ?: throw IOException("index error: ${body.error}")
|
||||||
@@ -207,3 +207,4 @@ class ReleaseRepository(private val httpClient: OkHttpClient) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@@ -3,17 +3,18 @@ package com.geode.launcher.utils
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.FileUtils
|
import android.os.FileUtils
|
||||||
import kotlinx.coroutines.runInterruptible
|
import kotlinx.coroutines.runInterruptible
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import okhttp3.Call
|
|
||||||
import okhttp3.Callback
|
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.RequestBody
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
|
import okhttp3.coroutines.executeAsync
|
||||||
import okio.Buffer
|
import okio.Buffer
|
||||||
|
import okio.BufferedSink
|
||||||
import okio.BufferedSource
|
import okio.BufferedSource
|
||||||
|
import okio.ForwardingSink
|
||||||
import okio.ForwardingSource
|
import okio.ForwardingSource
|
||||||
|
import okio.Sink
|
||||||
import okio.Source
|
import okio.Source
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@@ -21,8 +22,6 @@ import java.io.InputStream
|
|||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
import kotlin.coroutines.resume
|
|
||||||
import kotlin.coroutines.resumeWithException
|
|
||||||
|
|
||||||
|
|
||||||
typealias ProgressCallback = (progress: Long, outOf: Long) -> Unit
|
typealias ProgressCallback = (progress: Long, outOf: Long) -> Unit
|
||||||
@@ -50,7 +49,7 @@ object DownloadUtils {
|
|||||||
val originalResponse = chain.proceed(chain.request())
|
val originalResponse = chain.proceed(chain.request())
|
||||||
originalResponse.newBuilder()
|
originalResponse.newBuilder()
|
||||||
.body(ProgressResponseBody(
|
.body(ProgressResponseBody(
|
||||||
originalResponse.body!!, onProgress
|
originalResponse.body, onProgress
|
||||||
))
|
))
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
@@ -59,30 +58,8 @@ object DownloadUtils {
|
|||||||
val progressClient = progressClientBuilder.build()
|
val progressClient = progressClientBuilder.build()
|
||||||
|
|
||||||
val call = progressClient.newCall(request)
|
val call = progressClient.newCall(request)
|
||||||
val response = call.executeCoroutine()
|
return call.executeAsync().use { response ->
|
||||||
|
response.body.byteStream()
|
||||||
return response.body!!.byteStream()
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun Call.executeCoroutine(): Response {
|
|
||||||
return suspendCancellableCoroutine { continuation ->
|
|
||||||
this.enqueue(object : Callback {
|
|
||||||
override fun onFailure(call: Call, e: IOException) {
|
|
||||||
if (continuation.isCancelled) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
continuation.resumeWithException(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) {
|
|
||||||
continuation.resume(response)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
continuation.invokeOnCancellation {
|
|
||||||
this.cancel()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,3 +144,38 @@ private class ProgressResponseBody (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now based on <https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/UploadProgress.java#L84>
|
||||||
|
class ProgressRequestBody(
|
||||||
|
private val requestBody: RequestBody,
|
||||||
|
private val progressCallback: ProgressCallback
|
||||||
|
) : RequestBody() {
|
||||||
|
override fun contentType(): MediaType? {
|
||||||
|
return requestBody.contentType()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun contentLength(): Long {
|
||||||
|
return requestBody.contentLength()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeTo(sink: BufferedSink) {
|
||||||
|
val bufferedSink = this.sink(sink).buffer()
|
||||||
|
requestBody.writeTo(bufferedSink)
|
||||||
|
bufferedSink.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sink(sink: Sink): Sink {
|
||||||
|
return object : ForwardingSink(sink) {
|
||||||
|
var totalBytesWritten = 0L
|
||||||
|
|
||||||
|
override fun write(source: Buffer, byteCount: Long) {
|
||||||
|
super.write(source, byteCount)
|
||||||
|
totalBytesWritten += byteCount
|
||||||
|
progressCallback(
|
||||||
|
totalBytesWritten,
|
||||||
|
contentLength()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user