From 1ceb53d2d47f6ad030420071df22e03c1e3b936b Mon Sep 17 00:00:00 2001 From: X1nto Date: Sat, 16 Jan 2021 18:36:46 +0400 Subject: [PATCH] retrofit goes brrrrrr --- app/src/main/AndroidManifest.xml | 1 - .../core/downloader/MicrogDownloader.kt | 16 ++- .../core/downloader/MusicDownloader.kt | 6 +- .../core/downloader/VancedDownloader.kt | 82 ++++++------ .../com/vanced/manager/model/ProgressModel.kt | 4 +- .../vanced/manager/utils/DownloadHelper.kt | 126 ++++++++++++++---- .../network/providers/RetrofitProvider.kt | 11 +- 7 files changed, 165 insertions(+), 81 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 31ebd398..620ade3f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -31,7 +31,6 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:largeHeap="true" tools:ignore="UnusedAttribute"> throw NotImplementedError("This type of APK is NOT valid. What the hell did you even do?") } - fuelDownload(url, folderName!!, getFileNameFromUrl(url), context, onDownloadComplete = { - when (type) { - "theme" -> - if (variant == "root") { - if (validateTheme(downloadPath!!, theme!!, hashUrl, context)) { - if (downloadStockCheck(vancedRootPkg, vancedVersionCode, context)) - downloadSplits(context, "arch") - else - startVancedInstall(context) + installUrl?.let { + download(url, "$it/", folderName!!, getFileNameFromUrl(url), context, onDownloadComplete = { + when (type) { + "theme" -> + if (variant == "root") { + if (validateTheme(downloadPath!!, theme!!, hashUrl, context)) { + if (downloadStockCheck(vancedRootPkg, vancedVersionCode, context)) + downloadSplits(context, "arch") + else + startVancedInstall(context) + } else + downloadSplits(context, "theme") } else - downloadSplits(context, "theme") - } else - downloadSplits(context, "arch") - "arch" -> if (variant == "root") downloadSplits(context, "stock") else downloadSplits(context, "lang") - "stock" -> downloadSplits(context, "dpi") - "dpi" -> downloadSplits(context, "lang") - "lang" -> { - count++ - succesfulLangCount++ - if (count < lang.size) - downloadSplits(context, "lang") - else - startVancedInstall(context) - } - - } - }, onError = { - if (type == "lang") { - count++ - when { - count < lang.size -> downloadSplits(context, "lang") - succesfulLangCount == 0 -> { - lang.add("en") - downloadSplits(context, "lang") + downloadSplits(context, "arch") + "arch" -> if (variant == "root") downloadSplits(context, "stock") else downloadSplits(context, "lang") + "stock" -> downloadSplits(context, "dpi") + "dpi" -> downloadSplits(context, "lang") + "lang" -> { + count++ + succesfulLangCount++ + if (count < lang.size) + downloadSplits(context, "lang") + else + startVancedInstall(context) } - else -> startVancedInstall(context) - } - } else { - downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, getFileNameFromUrl(url))) - } - }) + } + }, onError = { + if (type == "lang") { + count++ + when { + count < lang.size -> downloadSplits(context, "lang") + succesfulLangCount == 0 -> { + lang.add("en") + downloadSplits(context, "lang") + } + else -> startVancedInstall(context) + } + + } else { + downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, getFileNameFromUrl(url))) + } + }) + } } fun startVancedInstall(context: Context, variant: String? = this.variant) { diff --git a/app/src/main/java/com/vanced/manager/model/ProgressModel.kt b/app/src/main/java/com/vanced/manager/model/ProgressModel.kt index 990d96cc..6aa723e9 100644 --- a/app/src/main/java/com/vanced/manager/model/ProgressModel.kt +++ b/app/src/main/java/com/vanced/manager/model/ProgressModel.kt @@ -2,6 +2,8 @@ package com.vanced.manager.model import androidx.lifecycle.MutableLiveData import com.github.kittinunf.fuel.core.requests.CancellableRequest +import okhttp3.ResponseBody +import retrofit2.Call open class ProgressModel { @@ -9,7 +11,7 @@ open class ProgressModel { val downloadingFile = MutableLiveData() val installing = MutableLiveData() - var currentDownload: CancellableRequest? = null + var currentDownload: Call? = null fun reset() { downloadProgress.value = 0 diff --git a/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt b/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt index 3bcf95ff..7a9b616f 100644 --- a/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt +++ b/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt @@ -7,43 +7,106 @@ import android.os.Build import android.util.Log import androidx.core.content.FileProvider import androidx.lifecycle.MutableLiveData -import com.github.kittinunf.fuel.Fuel import com.vanced.manager.R +import com.vanced.manager.library.network.providers.createService import com.vanced.manager.model.ProgressModel import com.vanced.manager.utils.AppUtils.sendCloseDialog import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import java.io.File +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.Streaming +import retrofit2.http.Url +import java.io.* object DownloadHelper : CoroutineScope by CoroutineScope(Dispatchers.IO) { - fun fuelDownload(url: String, fileFolder: String, fileName: String, context: Context, onDownloadComplete: () -> Unit, onError: (error: String) -> Unit) = launch { - try { - downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.downloading_file, fileName)) - downloadProgress.value?.currentDownload = Fuel.download(url) - .fileDestination { _, _ -> - File(context.getExternalFilesDir(fileFolder)?.path, fileName) - } - .progress { readBytes, totalBytes -> - downloadProgress.value?.downloadProgress?.postValue((readBytes * 100 / totalBytes).toInt()) - } - .responseString { _, _, result -> - result.fold(success = { - downloadProgress.value?.downloadProgress?.postValue(0) - onDownloadComplete() - }, failure = { error -> - downloadProgress.value?.downloadProgress?.postValue(0) - Log.d("VMDownloader", error.cause.toString()) - onError(error.errorData.toString()) - }) - } - } catch (e: Exception) { - downloadProgress.value?.downloadProgress?.postValue(0) - Log.d("VMDownloader", "Failed to download file: $url") - onError("") - } + interface DownloadHelper { + @Streaming + @GET + fun download(@Url url: String): Call + + } + + fun download( + url: String, + baseUrl: String, + fileFolder: String, + fileName: String, + context: Context, + onDownloadComplete: () -> Unit, + onError: (error: String) -> Unit + ) { + downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.downloading_file, fileName)) + val downloadInterface = createService(DownloadHelper::class, baseUrl) + val download = downloadInterface.download(url) + downloadProgress.value?.currentDownload = download + download.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + CoroutineScope(Dispatchers.IO).launch { + if (response.body()?.let { writeFile(it, context.getExternalFilesDir(fileFolder)?.path + "/" + fileName) } == true) { + onDownloadComplete() + } else { + onError("Could not save file") + downloadProgress.value?.downloadProgress?.postValue(0) + Log.d("VMDownloader", "Failed to download file: $url") + } + } + } else { + onError(response.errorBody().toString()) + downloadProgress.value?.downloadProgress?.postValue(0) + Log.d("VMDownloader", "Failed to download file: $url") + } + } + + override fun onFailure(call: Call, t: Throwable) { + if (call.isCanceled) { + Log.d("VMDownloader", "Download canceled") + downloadProgress.value?.downloadProgress?.postValue(0) + } else { + onError(t.stackTraceToString()) + downloadProgress.value?.downloadProgress?.postValue(0) + Log.d("VMDownloader", "Failed to download file: $url") + } + } + + }) + } + + fun writeFile(body: ResponseBody, filePath: String): Boolean { + return try { + val file = File(filePath) + val totalBytes = body.contentLength() + var inputStream: InputStream? = null + var outputStream: OutputStream? = null + try { + val fileReader = ByteArray(4096) + var downloadedBytes: Long = 0 + inputStream = body.byteStream() + outputStream = FileOutputStream(file) + var read: Int + while (inputStream.read(fileReader).also { read = it } != -1) { + outputStream.write(fileReader, 0, read) + downloadedBytes += read.toLong() + downloadProgress.value?.downloadProgress?.postValue((downloadedBytes * 100 / totalBytes).toInt()) + } + outputStream.flush() + true + } catch (e: IOException) { + false + } finally { + inputStream?.close() + outputStream?.close() + } + } catch (e: IOException) { + false + } } val downloadProgress = MutableLiveData() @@ -54,7 +117,7 @@ object DownloadHelper : CoroutineScope by CoroutineScope(Dispatchers.IO) { fun downloadManager(context: Context) { val url = "https://github.com/YTVanced/VancedManager/releases/latest/download/manager.apk" - fuelDownload(url, "manager", "manager.apk", context, onDownloadComplete = { + download(url,"https://github.com/YTVanced/VancedManager", "manager", "manager.apk", context, onDownloadComplete = { val apk = File("${context.getExternalFilesDir("manager")?.path}/manager.apk") val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) @@ -69,7 +132,12 @@ object DownloadHelper : CoroutineScope by CoroutineScope(Dispatchers.IO) { context.startActivity(intent) sendCloseDialog(context) }, onError = { - downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, "manager.apk")) + downloadProgress.value?.downloadingFile?.postValue( + context.getString( + R.string.error_downloading, + "manager.apk" + ) + ) }) } diff --git a/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt b/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt index 6ecccda4..edafe26b 100644 --- a/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt +++ b/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt @@ -4,6 +4,7 @@ import com.squareup.moshi.Moshi import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory +import kotlin.reflect.KClass fun provideRetrofit( okHttpClient: OkHttpClient, @@ -13,4 +14,12 @@ fun provideRetrofit( .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(okHttpClient) .baseUrl(url) - .build() \ No newline at end of file + .build() + +fun createService(service: KClass, baseurl: String): S { + return provideRetrofit( + provideOkHttpClient(), + provideMoshi(), + baseurl + ).create(service.java) +} \ No newline at end of file