retrofit goes brrrrrr

This commit is contained in:
X1nto 2021-01-16 18:36:46 +04:00
parent e670b5764e
commit 1ceb53d2d4
7 changed files with 165 additions and 81 deletions

View File

@ -31,7 +31,6 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:largeHeap="true"
tools:ignore="UnusedAttribute">
<activity

View File

@ -2,8 +2,10 @@ package com.vanced.manager.core.downloader
import android.content.Context
import com.vanced.manager.R
import com.vanced.manager.utils.DownloadHelper.download
import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.DownloadHelper.fuelDownload
import com.vanced.manager.utils.Extensions.getDefaultPrefs
import com.vanced.manager.utils.Extensions.getInstallUrl
import com.vanced.manager.utils.InternetTools.microg
import com.vanced.manager.utils.PackageHelper.install
@ -14,11 +16,13 @@ object MicrogDownloader {
fun downloadMicrog(context: Context) {
val url = microg.value?.string("url") ?: ""
fuelDownload(url, folderName, fileName, context, onDownloadComplete = {
startMicrogInstall(context)
}, onError = {
downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, fileName))
})
context.getDefaultPrefs().getInstallUrl()?.let {
download(url, "$it/", folderName, fileName, context, onDownloadComplete = {
startMicrogInstall(context)
}, onError = {
downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, fileName))
})
}
}

View File

@ -6,8 +6,8 @@ import com.vanced.manager.R
import com.vanced.manager.utils.AppUtils.musicRootPkg
import com.vanced.manager.utils.AppUtils.validateTheme
import com.vanced.manager.utils.DeviceUtils.getArch
import com.vanced.manager.utils.DownloadHelper.download
import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.DownloadHelper.fuelDownload
import com.vanced.manager.utils.Extensions.getInstallUrl
import com.vanced.manager.utils.Extensions.getLatestAppVersion
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl
@ -42,10 +42,10 @@ object MusicDownloader {
private fun downloadApk(context: Context, apk: String = "music") {
val url = if (apk == "stock") "$baseurl/stock/${getArch()}.apk" else "$baseurl/$variant.apk"
fuelDownload(url, folderName!!, getFileNameFromUrl(url), context, onDownloadComplete = {
download(url, baseurl + "/", folderName!!, getFileNameFromUrl(url), context, onDownloadComplete = {
if (variant == "root" && apk != "stock") {
downloadApk(context, "stock")
return@fuelDownload
return@download
}
when (apk) {

View File

@ -9,8 +9,8 @@ import com.vanced.manager.R
import com.vanced.manager.utils.AppUtils.validateTheme
import com.vanced.manager.utils.AppUtils.vancedRootPkg
import com.vanced.manager.utils.DeviceUtils.getArch
import com.vanced.manager.utils.DownloadHelper.download
import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.DownloadHelper.fuelDownload
import com.vanced.manager.utils.Extensions.getInstallUrl
import com.vanced.manager.utils.Extensions.getLatestAppVersion
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl
@ -77,48 +77,50 @@ object VancedDownloader {
else -> 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) {

View File

@ -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<String>()
val installing = MutableLiveData<Boolean>()
var currentDownload: CancellableRequest? = null
var currentDownload: Call<ResponseBody>? = null
fun reset() {
downloadProgress.value = 0

View File

@ -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<ResponseBody>
}
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<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
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<ResponseBody>, 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<ProgressModel>()
@ -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"
)
)
})
}

View File

@ -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()
.build()
fun <S: Any> createService(service: KClass<S>, baseurl: String): S {
return provideRetrofit(
provideOkHttpClient(),
provideMoshi(),
baseurl
).create(service.java)
}