VancedManager/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt

225 lines
9.1 KiB
Kotlin
Raw Normal View History

2020-06-19 15:48:14 +00:00
package com.vanced.manager.core.downloader
import android.content.Context
2020-08-25 09:05:20 +00:00
import android.content.SharedPreferences
2020-06-19 15:48:14 +00:00
import android.os.Build
2020-08-05 11:52:09 +00:00
import android.widget.Toast
2020-09-20 14:41:28 +00:00
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
2020-08-02 16:16:55 +00:00
import com.downloader.Error
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.logEvent
2020-08-02 16:16:55 +00:00
import com.vanced.manager.R
2020-09-20 14:41:28 +00:00
import com.vanced.manager.core.App
2020-09-06 10:33:04 +00:00
import com.vanced.manager.ui.viewmodels.HomeViewModel.Companion.vancedProgress
2020-09-20 14:41:28 +00:00
import com.vanced.manager.utils.AppUtils.mutableInstall
import com.vanced.manager.utils.InternetTools
2020-06-29 16:45:47 +00:00
import com.vanced.manager.utils.InternetTools.baseUrl
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl
import com.vanced.manager.utils.PackageHelper.getPkgVerCode
2020-09-06 10:33:04 +00:00
import com.vanced.manager.utils.PackageHelper.installVanced
2020-09-15 18:06:29 +00:00
import com.vanced.manager.utils.PackageHelper.installVancedRoot
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
2020-07-11 21:43:43 +00:00
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.File
import java.io.IOException
import java.security.MessageDigest
2020-09-29 17:42:03 +00:00
import java.util.*
2020-06-19 15:48:14 +00:00
2020-09-06 10:33:04 +00:00
object VancedDownloader {
2020-06-19 15:48:14 +00:00
private var sha256Val: String? = null
2020-08-25 09:05:20 +00:00
private lateinit var prefs: SharedPreferences
private lateinit var defPrefs: SharedPreferences
private lateinit var arch: String
private var installUrl: String? = null
private var variant: String? = null
private var theme: String? = null
private var lang: Array<String>? = null
private lateinit var themePath: String
2020-08-02 16:16:55 +00:00
private var count: Int = 0
private var hashUrl = ""
private const val yPkg = "com.google.android.youtube"
2020-09-15 18:06:29 +00:00
private var vancedVersionCode = 0
private var vancedVersion: String? = null
2020-07-01 15:10:34 +00:00
fun downloadVanced(context: Context){
val app = context.applicationContext as App
2020-09-06 10:33:04 +00:00
File(context.getExternalFilesDir("apks")?.path as String).deleteRecursively()
2020-09-20 14:41:28 +00:00
defPrefs = getDefaultSharedPreferences(context)
2020-08-25 09:05:20 +00:00
installUrl = defPrefs.getString("install_url", baseUrl)
2020-09-15 18:06:29 +00:00
prefs = context.getSharedPreferences("installPrefs", Context.MODE_PRIVATE)
2020-08-25 09:05:20 +00:00
variant = defPrefs.getString("vanced_variant", "nonroot")
lang = prefs.getString("lang", "en")?.split(", ")?.toTypedArray()
theme = prefs.getString("theme", "dark")
vancedVersion = app.vanced.get()?.string("version")
2020-08-25 09:05:20 +00:00
themePath = "$installUrl/apks/v$vancedVersion/$variant/Theme"
hashUrl = "apks/v$vancedVersion/$variant/Theme/hash.json"
2020-09-17 10:13:16 +00:00
//newInstaller = defPrefs.getBoolean("new_installer", false)
2020-08-25 09:05:20 +00:00
arch =
when {
Build.SUPPORTED_ABIS.contains("x86") -> "x86"
Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a"
else -> "armeabi_v7a"
}
vancedVersionCode = app.vanced.get()?.int("versionCode") ?: 0
2020-09-06 10:33:04 +00:00
downloadSplits(context)
2020-06-19 15:48:14 +00:00
}
2020-09-15 18:06:29 +00:00
private fun downloadSplits(
2020-09-06 10:33:04 +00:00
context: Context,
type: String = "theme"
2020-06-19 15:48:14 +00:00
) {
CoroutineScope(Dispatchers.IO).launch {
val url =
when (type) {
"theme" -> "$themePath/$theme.apk"
2020-08-25 09:05:20 +00:00
"arch" -> "$installUrl/apks/v$vancedVersion/$variant/Arch/split_config.$arch.apk"
2020-09-26 17:09:01 +00:00
"stock" -> "$themePath/stock.apk"
2020-08-23 00:48:48 +00:00
"dpi" -> "$themePath/dpi.apk"
2020-08-25 09:05:20 +00:00
"lang" -> "$installUrl/apks/v$vancedVersion/$variant/Language/split_config.${lang?.get(count)}.apk"
else -> throw NotImplementedError("This type of APK is NOT valid. What the hell did you even do?")
}
2020-06-19 15:48:14 +00:00
vancedProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("apks")?.path, getFileNameFromUrl(url))
2020-09-06 10:33:04 +00:00
.build()
.setOnStartOrResumeListener {
2020-09-20 14:41:28 +00:00
mutableInstall.value = true
2020-09-17 10:13:16 +00:00
vancedProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, getFileNameFromUrl(url)))
vancedProgress.get()?.showDownloadBar?.set(true)
2020-09-06 10:33:04 +00:00
}
.setOnProgressListener { progress ->
2020-09-17 10:13:16 +00:00
vancedProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt())
2020-09-06 10:33:04 +00:00
}
.setOnCancelListener {
mutableInstall.value = false
vancedProgress.get()?.showDownloadBar?.set(false)
}
2020-09-06 10:33:04 +00:00
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
when (type) {
"theme" ->
2020-09-17 10:13:16 +00:00
if (variant == "root") {
2020-09-15 18:06:29 +00:00
if (validateTheme(context)) {
2020-09-29 17:42:03 +00:00
if (downloadStockCheck(context))
2020-09-06 10:33:04 +00:00
downloadSplits(context, "arch")
else
2020-09-15 18:06:29 +00:00
prepareInstall(variant!!, context)
2020-09-06 10:33:04 +00:00
} else
downloadSplits(context, "theme")
2020-08-25 09:05:20 +00:00
} else
2020-09-06 10:33:04 +00:00
downloadSplits(context, "arch")
2020-09-17 10:13:16 +00:00
"arch" -> if (variant == "root") downloadSplits(context, "stock") else downloadSplits(context, "lang")
2020-09-06 10:33:04 +00:00
"stock" -> downloadSplits(context, "dpi")
"dpi" -> downloadSplits(context, "lang")
"lang" -> {
count++
if (count < lang?.count()!!)
downloadSplits(context, "lang")
else
2020-09-15 18:06:29 +00:00
prepareInstall(variant!!, context)
2020-09-06 10:33:04 +00:00
}
}
}
override fun onError(error: Error?) {
if (type == "lang") {
count++
if (count < lang?.count()!!)
2020-09-06 10:33:04 +00:00
downloadSplits(context, "lang")
else
2020-09-15 18:06:29 +00:00
prepareInstall(variant!!, context)
2020-09-06 10:33:04 +00:00
} else {
2020-09-30 15:27:11 +00:00
count = 0
2020-09-20 14:41:28 +00:00
mutableInstall.value = false
2020-09-17 10:13:16 +00:00
vancedProgress.get()?.showDownloadBar?.set(false)
2020-09-26 17:09:01 +00:00
Toast.makeText(context, context.getString(R.string.error_downloading, getFileNameFromUrl(url)), Toast.LENGTH_SHORT).show()
2020-06-19 15:48:14 +00:00
}
2020-09-04 19:14:43 +00:00
}
2020-09-06 10:33:04 +00:00
})
2020-08-02 16:16:55 +00:00
}
2020-07-10 19:09:51 +00:00
}
2020-09-15 18:06:29 +00:00
private fun downloadStockCheck(context: Context) :Boolean {
2020-08-25 09:05:20 +00:00
return try {
getPkgVerCode(yPkg,context.packageManager) != vancedVersionCode
2020-08-25 09:05:20 +00:00
} catch (e: Exception) {
true
}
}
2020-08-25 09:05:20 +00:00
2020-09-15 18:06:29 +00:00
private suspend fun getSha256(obj: String, context: Context) {
sha256Val = InternetTools.getJsonString(hashUrl, obj, context)
}
2020-08-25 09:05:20 +00:00
2020-09-15 18:06:29 +00:00
private fun validateTheme(context: Context): Boolean {
val themeS = context.getExternalFilesDir("apks")?.path + "/${theme}.apk"
val themeF = File(themeS)
2020-09-15 18:06:29 +00:00
runBlocking { getSha256(theme!!, context) }
return checkSHA256(sha256Val!!,themeF)
}
2020-09-06 10:33:04 +00:00
private fun prepareInstall(variant: String, context: Context) {
2020-09-30 15:27:11 +00:00
count = 0
2020-09-17 10:13:16 +00:00
vancedProgress.get()?.showDownloadBar?.set(false)
vancedProgress.get()?.showInstallCircle?.set(true)
FirebaseAnalytics.getInstance(context).logEvent(FirebaseAnalytics.Event.SELECT_ITEM) {
2020-09-30 15:48:28 +00:00
param("vanced_variant", variant)
theme?.let { param("vanced_theme", it) }
}
2020-06-21 20:05:48 +00:00
if (variant == "root")
2020-09-06 10:33:04 +00:00
installVancedRoot(context)
2020-06-21 20:05:48 +00:00
else
2020-09-15 18:06:29 +00:00
installVanced(context)
2020-06-19 15:48:14 +00:00
}
private fun checkSHA256(sha256: String, updateFile: File?): Boolean {
return try {
val dataBuffer = updateFile!!.readBytes()
// Generate the checksum
val sum = generateChecksum(dataBuffer)
2020-09-29 17:42:03 +00:00
sum.toLowerCase(Locale.ENGLISH) == sha256.toLowerCase(Locale.ENGLISH)
} catch (e: Exception) {
e.printStackTrace()
false
}
}
@Throws(IOException::class)
private fun generateChecksum(data: ByteArray): String {
try {
val digest: MessageDigest = MessageDigest.getInstance("SHA-256")
val hash: ByteArray = digest.digest(data)
return printableHexString(hash)
} catch (e: Exception) {
e.printStackTrace()
}
return ""
}
private fun printableHexString(data: ByteArray): String {
// Create Hex String
val hexString: StringBuilder = StringBuilder()
for (aMessageDigest:Byte in data) {
var h: String = Integer.toHexString(0xFF and aMessageDigest.toInt())
while (h.length < 2)
h = "0$h"
hexString.append(h)
}
return hexString.toString()
}
2020-08-25 09:05:20 +00:00
}