Switched to Fuel downloader

This commit is contained in:
Xinto 2020-11-23 20:00:41 +04:00
parent a1827fd8c7
commit dd3dba0fad
23 changed files with 186 additions and 292 deletions

View File

@ -75,7 +75,7 @@ def getLanguages() {
langs.add("pt_PT") langs.add("pt_PT")
langs.add("zh_CN") langs.add("zh_CN")
langs.add("zh_TW") langs.add("zh_TW")
List<String> exceptions = [ "bn", "pt", "zh"] List<String> exceptions = ["bn", "pt", "zh"]
Pattern pattern = Pattern.compile("-(\\w+)-") Pattern pattern = Pattern.compile("-(\\w+)-")
new File("${projectDir}/src/main/res").eachDir { dir -> new File("${projectDir}/src/main/res").eachDir { dir ->
if (dir.name.startsWith("values-") && !dir.name.contains("v23")) { if (dir.name.startsWith("values-") && !dir.name.contains("v23")) {
@ -139,9 +139,6 @@ dependencies {
// Layout // Layout
implementation 'com.google.android:flexbox:2.0.1' implementation 'com.google.android:flexbox:2.0.1'
// File downloader
implementation 'com.mindorks.android:prdownloader:0.6.0'
// Firebase // Firebase
implementation 'com.google.firebase:firebase-analytics-ktx:18.0.0' implementation 'com.google.firebase:firebase-analytics-ktx:18.0.0'
implementation 'com.google.firebase:firebase-crashlytics:17.3.0' implementation 'com.google.firebase:firebase-crashlytics:17.3.0'

View File

@ -8,7 +8,6 @@ import com.crowdin.platform.Crowdin
import com.crowdin.platform.CrowdinConfig import com.crowdin.platform.CrowdinConfig
import com.crowdin.platform.data.model.AuthConfig import com.crowdin.platform.data.model.AuthConfig
import com.crowdin.platform.data.remote.NetworkType import com.crowdin.platform.data.remote.NetworkType
import com.downloader.PRDownloader
import com.vanced.manager.BuildConfig.* import com.vanced.manager.BuildConfig.*
import com.vanced.manager.utils.InternetTools.loadJson import com.vanced.manager.utils.InternetTools.loadJson
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -24,7 +23,6 @@ open class App: Application() {
override fun onCreate() { override fun onCreate() {
scope.launch { loadJson(this@App) } scope.launch { loadJson(this@App) }
super.onCreate() super.onCreate()
PRDownloader.initialize(this)
Crowdin.init(this, Crowdin.init(this,
CrowdinConfig.Builder().apply { CrowdinConfig.Builder().apply {

View File

@ -1,48 +1,30 @@
package com.vanced.manager.core.downloader package com.vanced.manager.core.downloader
import android.content.Context import android.content.Context
import com.downloader.Error
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.utils.DownloadHelper.downloadProgress import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl import com.vanced.manager.utils.DownloadHelper.fuelDownload
import com.vanced.manager.utils.InternetTools.microg import com.vanced.manager.utils.InternetTools.microg
import com.vanced.manager.utils.PackageHelper.install import com.vanced.manager.utils.PackageHelper.install
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
object MicrogDownloader : CoroutineScope by CoroutineScope(Dispatchers.IO) { object MicrogDownloader {
fun downloadMicrog( private const val fileName = "microg.apk"
context: Context, private const val folderName = "microg"
) = launch {
val url = microg.get()?.string("url")
downloadProgress.value?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("microg")?.path, "microg.apk") fun downloadMicrog(context: Context) {
.build() val url = microg.get()?.string("url") ?: ""
.setOnStartOrResumeListener { fuelDownload(url, folderName, fileName, context, onDownloadComplete = {
downloadProgress.value?.downloadingFile?.value = context.getString(R.string.downloading_file, url?.let { getFileNameFromUrl(it) }) startMicrogInstall(context)
} }, onError = {
.setOnProgressListener { progress -> downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, fileName))
downloadProgress.value?.downloadProgress?.value = (progress.currentBytes * 100 / progress.totalBytes).toInt() })
}
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
startMicrogInstall(context)
}
override fun onError(error: Error?) { }
downloadProgress.value?.downloadingFile?.value = context.getString(R.string.error_downloading, "microG")
}
})
}
fun startMicrogInstall(context: Context) { fun startMicrogInstall(context: Context) {
downloadProgress.value?.installing?.value = true downloadProgress.value?.installing?.postValue(true)
downloadProgress.value?.reset() downloadProgress.value?.postReset()
install("${context.getExternalFilesDir("microg")}/microg.apk", context) install("${context.getExternalFilesDir(folderName)}/$fileName", context)
} }
} }

View File

@ -2,34 +2,28 @@ package com.vanced.manager.core.downloader
import android.content.Context import android.content.Context
import androidx.preference.PreferenceManager.getDefaultSharedPreferences import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.downloader.Error
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.utils.AppUtils.musicRootPkg import com.vanced.manager.utils.AppUtils.musicRootPkg
import com.vanced.manager.utils.AppUtils.validateTheme import com.vanced.manager.utils.AppUtils.validateTheme
import com.vanced.manager.utils.DeviceUtils.getArch import com.vanced.manager.utils.DeviceUtils.getArch
import com.vanced.manager.utils.DownloadHelper.downloadProgress 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.getInstallUrl
import com.vanced.manager.utils.Extensions.getLatestAppVersion import com.vanced.manager.utils.Extensions.getLatestAppVersion
import com.vanced.manager.utils.InternetTools.backupUrl
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl import com.vanced.manager.utils.InternetTools.getFileNameFromUrl
import com.vanced.manager.utils.InternetTools.music import com.vanced.manager.utils.InternetTools.music
import com.vanced.manager.utils.InternetTools.musicVersions import com.vanced.manager.utils.InternetTools.musicVersions
import com.vanced.manager.utils.PackageHelper.downloadStockCheck import com.vanced.manager.utils.PackageHelper.downloadStockCheck
import com.vanced.manager.utils.PackageHelper.install import com.vanced.manager.utils.PackageHelper.install
import com.vanced.manager.utils.PackageHelper.installMusicRoot import com.vanced.manager.utils.PackageHelper.installMusicRoot
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlin.coroutines.suspendCoroutine
object MusicDownloader: CoroutineScope by CoroutineScope(Dispatchers.IO) { object MusicDownloader {
private var variant: String? = null private var variant: String? = null
private var version: String? = null private var version: String? = null
private var versionCode: Int? = null private var versionCode: Int? = null
private var baseurl = "" private var baseurl = ""
private var folderName: String? = null
private var downloadPath: String? = null private var downloadPath: String? = null
private var hashUrl: String? = null private var hashUrl: String? = null
@ -39,68 +33,45 @@ object MusicDownloader: CoroutineScope by CoroutineScope(Dispatchers.IO) {
versionCode = music.get()?.int("versionCode") versionCode = music.get()?.int("versionCode")
variant = prefs.getString("vanced_variant", "nonroot") variant = prefs.getString("vanced_variant", "nonroot")
baseurl = "${prefs.getInstallUrl()}/music/v$version" baseurl = "${prefs.getInstallUrl()}/music/v$version"
downloadPath = context.getExternalFilesDir("music/$variant")?.path folderName = "music/$variant"
downloadPath = context.getExternalFilesDir(folderName)?.path
hashUrl = "$baseurl/hash.json" hashUrl = "$baseurl/hash.json"
downloadApk(context) downloadApk(context)
} }
private fun downloadApk(context: Context, apk: String = "music") { private fun downloadApk(context: Context, apk: String = "music") {
launch { val url = if (apk == "stock") "$baseurl/stock/${getArch()}.apk" else "$baseurl/$variant.apk"
val url = if (apk == "stock") "$baseurl/stock/${getArch()}.apk" else "$baseurl/$variant.apk" fuelDownload(url, folderName!!, getFileNameFromUrl(url), context, onDownloadComplete = {
suspendCoroutine { if (variant == "root" && apk != "stock") {
downloadProgress.value?.currentDownload = PRDownloader.download(url, downloadPath, getFileNameFromUrl(url)) downloadApk(context, "stock")
.build() return@fuelDownload
.setOnStartOrResumeListener {
downloadProgress.value?.downloadingFile?.value =context.getString(R.string.downloading_file, getFileNameFromUrl(url))
}
.setOnProgressListener { progress ->
downloadProgress.value?.downloadProgress?.value = (progress.currentBytes * 100 / progress.totalBytes).toInt()
}
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
if (variant == "root" && apk != "stock") {
downloadApk(context, "stock") // recursive in coroutine its so bad...
return
}
when (apk) {
"music" -> {
if (variant == "root") {
if (validateTheme(downloadPath!!, "root", hashUrl!!, context)) {
if (downloadStockCheck(musicRootPkg, versionCode!!, context))
downloadApk(context, "stock")
else
startMusicInstall(context)
} else {
downloadApk(context, apk)
}
} else
startMusicInstall(context)
}
}
startMusicInstall(context)
}
override fun onError(error: Error?) {
if (baseurl != backupUrl) {
baseurl = "$backupUrl/music/v$version"
downloadApk(context, apk)
return
}
downloadProgress.value?.downloadingFile?.value = context.getString(R.string.error_downloading, "Music")
}
})
} }
} when (apk) {
"music" -> {
if (variant == "root") {
if (validateTheme(downloadPath!!, "root", hashUrl!!, context)) {
if (downloadStockCheck(musicRootPkg, versionCode!!, context))
downloadApk(context, "stock")
else
startMusicInstall(context)
} else {
downloadApk(context, apk)
}
} else
startMusicInstall(context)
}
"stock" -> startMusicInstall(context)
}
}, onError = {
downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, getFileNameFromUrl(url)))
})
} }
fun startMusicInstall(context: Context) { fun startMusicInstall(context: Context) {
downloadProgress.value?.installing?.value = true downloadProgress.value?.installing?.postValue(true)
downloadProgress.value?.reset() downloadProgress.value?.postReset()
if (variant == "root") if (variant == "root")
installMusicRoot(context) installMusicRoot(context)
else else

View File

@ -3,9 +3,6 @@ package com.vanced.manager.core.downloader
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.preference.PreferenceManager.getDefaultSharedPreferences import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.downloader.Error
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.logEvent import com.google.firebase.analytics.ktx.logEvent
import com.vanced.manager.R import com.vanced.manager.R
@ -13,9 +10,9 @@ import com.vanced.manager.utils.AppUtils.validateTheme
import com.vanced.manager.utils.AppUtils.vancedRootPkg import com.vanced.manager.utils.AppUtils.vancedRootPkg
import com.vanced.manager.utils.DeviceUtils.getArch import com.vanced.manager.utils.DeviceUtils.getArch
import com.vanced.manager.utils.DownloadHelper.downloadProgress 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.getInstallUrl
import com.vanced.manager.utils.Extensions.getLatestAppVersion import com.vanced.manager.utils.Extensions.getLatestAppVersion
import com.vanced.manager.utils.InternetTools.backupUrl
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl import com.vanced.manager.utils.InternetTools.getFileNameFromUrl
import com.vanced.manager.utils.InternetTools.vanced import com.vanced.manager.utils.InternetTools.vanced
import com.vanced.manager.utils.InternetTools.vancedVersions import com.vanced.manager.utils.InternetTools.vancedVersions
@ -23,12 +20,9 @@ import com.vanced.manager.utils.LanguageHelper.getDefaultVancedLanguages
import com.vanced.manager.utils.PackageHelper.downloadStockCheck import com.vanced.manager.utils.PackageHelper.downloadStockCheck
import com.vanced.manager.utils.PackageHelper.installVanced import com.vanced.manager.utils.PackageHelper.installVanced
import com.vanced.manager.utils.PackageHelper.installVancedRoot import com.vanced.manager.utils.PackageHelper.installVancedRoot
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File import java.io.File
object VancedDownloader: CoroutineScope by CoroutineScope(Dispatchers.IO) { object VancedDownloader {
private lateinit var prefs: SharedPreferences private lateinit var prefs: SharedPreferences
private lateinit var defPrefs: SharedPreferences private lateinit var defPrefs: SharedPreferences
@ -48,12 +42,14 @@ object VancedDownloader: CoroutineScope by CoroutineScope(Dispatchers.IO) {
private var vancedVersion: String? = null private var vancedVersion: String? = null
private var downloadPath: String? = null private var downloadPath: String? = null
private var folderName: String? = null
fun downloadVanced(context: Context) { fun downloadVanced(context: Context) {
defPrefs = getDefaultSharedPreferences(context) defPrefs = getDefaultSharedPreferences(context)
prefs = context.getSharedPreferences("installPrefs", Context.MODE_PRIVATE) prefs = context.getSharedPreferences("installPrefs", Context.MODE_PRIVATE)
variant = defPrefs.getString("vanced_variant", "nonroot") variant = defPrefs.getString("vanced_variant", "nonroot")
downloadPath = context.getExternalFilesDir("vanced/$variant")?.path folderName = "vanced/$variant"
downloadPath = context.getExternalFilesDir(folderName)?.path
File(downloadPath.toString()).deleteRecursively() File(downloadPath.toString()).deleteRecursively()
installUrl = defPrefs.getInstallUrl() installUrl = defPrefs.getInstallUrl()
prefs.getString("lang", getDefaultVancedLanguages())?.let { prefs.getString("lang", getDefaultVancedLanguages())?.let {
@ -71,88 +67,63 @@ object VancedDownloader: CoroutineScope by CoroutineScope(Dispatchers.IO) {
downloadSplits(context) downloadSplits(context)
} }
private fun downloadSplits( private fun downloadSplits(context: Context, type: String = "theme") {
context: Context, val url = when (type) {
type: String = "theme" "theme" -> "$themePath/$theme.apk"
) { "arch" -> "$installUrl/apks/v$vancedVersion/$variant/Arch/split_config.$arch.apk"
launch { "stock" -> "$themePath/stock.apk"
val url = "dpi" -> "$themePath/dpi.apk"
when (type) { "lang" -> "$installUrl/apks/v$vancedVersion/$variant/Language/split_config.${lang[count]}.apk"
"theme" -> "$themePath/$theme.apk" else -> throw NotImplementedError("This type of APK is NOT valid. What the hell did you even do?")
"arch" -> "$installUrl/apks/v$vancedVersion/$variant/Arch/split_config.$arch.apk"
"stock" -> "$themePath/stock.apk"
"dpi" -> "$themePath/dpi.apk"
"lang" -> "$installUrl/apks/v$vancedVersion/$variant/Language/split_config.${lang[count]}.apk"
else -> throw NotImplementedError("This type of APK is NOT valid. What the hell did you even do?")
}
downloadProgress.value?.currentDownload = PRDownloader.download(url, downloadPath, getFileNameFromUrl(url))
.build()
.setOnStartOrResumeListener {
downloadProgress.value?.downloadingFile?.value = context.getString(R.string.downloading_file, getFileNameFromUrl(url))
}
.setOnProgressListener { progress ->
downloadProgress.value?.downloadProgress?.value = (progress.currentBytes * 100 / progress.totalBytes).toInt()
}
.start(object : OnDownloadListener {
override fun 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, "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)
}
}
}
override fun onError(error: Error?) {
if (installUrl != backupUrl) {
installUrl = backupUrl
themePath = "$installUrl/apks/v$vancedVersion/$variant/Theme"
downloadSplits(context, type)
return
}
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?.value = context.getString(R.string.error_downloading, getFileNameFromUrl(url))
}
}
})
} }
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)
} 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")
}
else -> startVancedInstall(context)
}
} else {
downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, getFileNameFromUrl(url)))
}
})
} }
fun startVancedInstall(context: Context, variant: String? = this.variant) { fun startVancedInstall(context: Context, variant: String? = this.variant) {
downloadProgress.value?.installing?.value = true downloadProgress.value?.installing?.postValue(true)
downloadProgress.value?.reset() downloadProgress.value?.postReset()
FirebaseAnalytics.getInstance(context).logEvent(FirebaseAnalytics.Event.SELECT_ITEM) { FirebaseAnalytics.getInstance(context).logEvent(FirebaseAnalytics.Event.SELECT_ITEM) {
variant?.let { param("vanced_variant", it) } variant?.let { param("vanced_variant", it) }
theme?.let { param("vanced_theme", it) } theme?.let { param("vanced_theme", it) }

View File

@ -1,6 +1,7 @@
package com.vanced.manager.model package com.vanced.manager.model
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.github.kittinunf.fuel.core.requests.CancellableRequest
open class ProgressModel { open class ProgressModel {
@ -8,13 +9,18 @@ open class ProgressModel {
val downloadingFile = MutableLiveData<String>() val downloadingFile = MutableLiveData<String>()
val installing = MutableLiveData<Boolean>() val installing = MutableLiveData<Boolean>()
var currentDownload: Int = 0 var currentDownload: CancellableRequest? = null
fun reset() { fun reset() {
downloadProgress.value = 0 downloadProgress.value = 0
downloadingFile.value = "" downloadingFile.value = ""
} }
fun postReset() {
downloadProgress.postValue(0)
downloadingFile.postValue("")
}
init { init {
installing.value = false installing.value = false
reset() reset()

View File

@ -13,11 +13,11 @@ import androidx.navigation.NavDestination
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager.* import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.crowdin.platform.Crowdin import com.crowdin.platform.Crowdin
import com.crowdin.platform.LoadingStateListener import com.crowdin.platform.LoadingStateListener
import com.google.firebase.messaging.FirebaseMessaging import com.google.firebase.messaging.FirebaseMessaging
import com.vanced.manager.BuildConfig.* import com.vanced.manager.BuildConfig.ENABLE_CROWDIN_AUTH
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.databinding.ActivityMainBinding import com.vanced.manager.databinding.ActivityMainBinding
import com.vanced.manager.ui.dialogs.DialogContainer import com.vanced.manager.ui.dialogs.DialogContainer

View File

@ -11,7 +11,6 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.downloader.PRDownloader
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.core.downloader.MicrogDownloader.downloadMicrog import com.vanced.manager.core.downloader.MicrogDownloader.downloadMicrog
import com.vanced.manager.core.downloader.MusicDownloader.downloadMusic import com.vanced.manager.core.downloader.MusicDownloader.downloadMusic
@ -91,7 +90,7 @@ class AppDownloadDialog : BindingDialogFragment<DialogAppDownloadBinding>() {
if (installing) { if (installing) {
return@setOnClickListener return@setOnClickListener
} }
PRDownloader.cancel(progressModel.currentDownload) progressModel.currentDownload?.cancel()
dismiss() dismiss()
} }
} }

View File

@ -2,7 +2,6 @@ package com.vanced.manager.ui.dialogs
import android.content.DialogInterface import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.edit import androidx.core.content.edit

View File

@ -3,7 +3,7 @@ package com.vanced.manager.ui.dialogs
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.preference.PreferenceManager.* import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.core.downloader.MicrogDownloader.startMicrogInstall import com.vanced.manager.core.downloader.MicrogDownloader.startMicrogInstall
import com.vanced.manager.core.downloader.MusicDownloader.startMusicInstall import com.vanced.manager.core.downloader.MusicDownloader.startMusicInstall

View File

@ -2,15 +2,10 @@ package com.vanced.manager.ui.dialogs
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.edit import androidx.core.content.edit
import androidx.databinding.DataBindingUtil
import androidx.preference.PreferenceManager.getDefaultSharedPreferences import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.radiobutton.MaterialRadioButton import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.R
import com.vanced.manager.databinding.DialogInstallationFilesDetectedBinding
import com.vanced.manager.databinding.DialogManagerAccentColorBinding import com.vanced.manager.databinding.DialogManagerAccentColorBinding
import com.vanced.manager.ui.core.BindingBottomSheetDialogFragment import com.vanced.manager.ui.core.BindingBottomSheetDialogFragment
import com.vanced.manager.utils.Extensions.getCheckedButtonTag import com.vanced.manager.utils.Extensions.getCheckedButtonTag

View File

@ -3,11 +3,12 @@ package com.vanced.manager.ui.dialogs
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.* import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager.* import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.radiobutton.MaterialRadioButton import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.BuildConfig.* import com.vanced.manager.BuildConfig.MANAGER_LANGUAGES
import com.vanced.manager.databinding.DialogManagerLanguageBinding import com.vanced.manager.databinding.DialogManagerLanguageBinding
import com.vanced.manager.ui.core.BindingBottomSheetDialogFragment import com.vanced.manager.ui.core.BindingBottomSheetDialogFragment
import com.vanced.manager.utils.Extensions.getCheckedButtonTag import com.vanced.manager.utils.Extensions.getCheckedButtonTag

View File

@ -4,7 +4,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager.* import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.radiobutton.MaterialRadioButton import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.databinding.DialogManagerThemeBinding import com.vanced.manager.databinding.DialogManagerThemeBinding
import com.vanced.manager.ui.core.BindingBottomSheetDialogFragment import com.vanced.manager.ui.core.BindingBottomSheetDialogFragment

View File

@ -10,22 +10,19 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.downloader.PRDownloader
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.databinding.DialogManagerUpdateBinding import com.vanced.manager.databinding.DialogManagerUpdateBinding
import com.vanced.manager.ui.core.BindingDialogFragment import com.vanced.manager.ui.core.BindingDialogFragment
import com.vanced.manager.utils.DownloadHelper.downloadManager import com.vanced.manager.utils.DownloadHelper.downloadManager
import com.vanced.manager.utils.DownloadHelper.downloadProgress import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.InternetTools.isUpdateAvailable import com.vanced.manager.utils.InternetTools.isUpdateAvailable
import kotlinx.coroutines.launch
class ManagerUpdateDialog : BindingDialogFragment<DialogManagerUpdateBinding>() { class ManagerUpdateDialog : BindingDialogFragment<DialogManagerUpdateBinding>() {
companion object { companion object {
const val CLOSE_DIALOG = "close_dialog" const val CLOSE_DIALOG = "CLOSE_DIALOG"
private const val TAG_FORCE_UPDATE = "TAG_FORCE_UPDATE" private const val TAG_FORCE_UPDATE = "TAG_FORCE_UPDATE"
fun newInstance( fun newInstance(
@ -56,18 +53,16 @@ class ManagerUpdateDialog : BindingDialogFragment<DialogManagerUpdateBinding>()
override fun otherSetups() { override fun otherSetups() {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
bindData() bindData()
lifecycleScope.launch { if (arguments?.getBoolean(TAG_FORCE_UPDATE) == true) {
if (arguments?.getBoolean(TAG_FORCE_UPDATE) == true) { binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient)
binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient) downloadManager(requireActivity())
downloadManager(requireActivity()) } else {
} else { checkUpdates()
checkUpdates() }
}
binding.managerUpdateCancel.setOnClickListener { binding.managerUpdateCancel.setOnClickListener {
PRDownloader.cancel(downloadProgress.value?.currentDownload) downloadProgress.value?.currentDownload?.cancel()
dismiss() dismiss()
}
} }
} }
@ -94,7 +89,7 @@ class ManagerUpdateDialog : BindingDialogFragment<DialogManagerUpdateBinding>()
registerReceiver() registerReceiver()
} }
private suspend fun checkUpdates() { private fun checkUpdates() {
if (isUpdateAvailable()) { if (isUpdateAvailable()) {
binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient) binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient)
downloadManager(requireActivity()) downloadManager(requireActivity())

View File

@ -4,7 +4,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager.* import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.radiobutton.MaterialRadioButton import com.google.android.material.radiobutton.MaterialRadioButton
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import com.vanced.manager.databinding.DialogManagerVariantBinding import com.vanced.manager.databinding.DialogManagerVariantBinding

View File

@ -5,7 +5,7 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager.* import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.adapter.SelectAppsAdapter import com.vanced.manager.adapter.SelectAppsAdapter

View File

@ -5,7 +5,8 @@ import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.* import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.Toast import android.widget.Toast
import androidx.core.content.edit import androidx.core.content.edit

View File

@ -4,11 +4,8 @@ import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.edit import androidx.core.content.edit
import androidx.databinding.DataBindingUtil
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.radiobutton.MaterialRadioButton import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.databinding.DialogBottomRadioButtonBinding import com.vanced.manager.databinding.DialogBottomRadioButtonBinding

View File

@ -10,7 +10,7 @@ import androidx.core.content.edit
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.preference.* import androidx.preference.*
import com.crowdin.platform.Crowdin import com.crowdin.platform.Crowdin
import com.vanced.manager.BuildConfig.* import com.vanced.manager.BuildConfig.ENABLE_CROWDIN_AUTH
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.ui.WelcomeActivity import com.vanced.manager.ui.WelcomeActivity
import com.vanced.manager.ui.dialogs.ManagerUpdateDialog import com.vanced.manager.ui.dialogs.ManagerUpdateDialog

View File

@ -32,8 +32,8 @@ import com.vanced.manager.ui.viewmodels.HomeViewModelFactory
open class HomeFragment : BindingFragment<FragmentHomeBinding>() { open class HomeFragment : BindingFragment<FragmentHomeBinding>() {
companion object { companion object {
const val INSTALL_FAILED = "install_failed" const val INSTALL_FAILED = "INSTALL_FAILED"
const val REFRESH_HOME = "refresh_home" const val REFRESH_HOME = "REFRESH_HOME"
} }
private val viewModel: HomeViewModel by viewModels { private val viewModel: HomeViewModel by viewModels {

View File

@ -10,5 +10,4 @@ object DeviceUtils {
else -> "armeabi_v7a" else -> "armeabi_v7a"
} }
} }

View File

@ -1,37 +1,41 @@
package com.vanced.manager.utils package com.vanced.manager.utils
import android.app.DownloadManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import android.widget.Toast
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.content.getSystemService
import androidx.core.net.toUri
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.downloader.OnDownloadListener import com.github.kittinunf.fuel.Fuel
import com.downloader.PRDownloader
import com.vanced.manager.R import com.vanced.manager.R
import com.vanced.manager.model.ProgressModel import com.vanced.manager.model.ProgressModel
import com.vanced.manager.utils.AppUtils.sendCloseDialog import com.vanced.manager.utils.AppUtils.sendCloseDialog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.launch
import java.io.File import java.io.File
object DownloadHelper { object DownloadHelper : CoroutineScope by CoroutineScope(Dispatchers.IO) {
fun download(url: String, dir: String, child: String, context: Context): Long { fun fuelDownload(url: String, fileFolder: String, fileName: String, context: Context, onDownloadComplete: () -> Unit, onError: (error: String) -> Unit) = launch {
val request = DownloadManager.Request(url.toUri()).apply { downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.downloading_file, fileName))
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI) downloadProgress.value?.currentDownload = Fuel.download(url)
setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE) .fileDestination { _, _ ->
setTitle(context.getString(R.string.downloading_file, child)) File(context.getExternalFilesDir(fileFolder)?.path, fileName)
setDestinationInExternalFilesDir(context, dir, child) }
} .progress { readBytes, totalBytes ->
downloadProgress.value?.downloadProgress?.postValue((readBytes * 100 / totalBytes).toInt())
val downloadManager = context.getSystemService<DownloadManager>()!! }
return downloadManager.enqueue(request) .responseString {_, _, result ->
result.fold(success = {
downloadProgress.value?.downloadProgress?.postValue(0)
onDownloadComplete()
}, failure = { error ->
Log.d("VMDownloader", error.errorData.toString())
onError(error.errorData.toString())
})
}
} }
val downloadProgress = MutableLiveData<ProgressModel>() val downloadProgress = MutableLiveData<ProgressModel>()
@ -40,46 +44,25 @@ object DownloadHelper {
downloadProgress.value = ProgressModel() downloadProgress.value = ProgressModel()
} }
suspend fun downloadManager(context: Context) = fun downloadManager(context: Context) {
withContext(Dispatchers.IO) { val url = "https://github.com/YTVanced/VancedManager/releases/latest/download/manager.apk"
val url = "https://github.com/YTVanced/VancedManager/releases/latest/download/manager.apk" fuelDownload(url, "manager", "manager.apk", context, onDownloadComplete = {
downloadProgress.value?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("manager")?.path, "manager.apk") val apk = File("${context.getExternalFilesDir("manager")?.path}/manager.apk")
.build() val uri =
.setOnProgressListener { progress -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
val mProgress = progress.currentBytes * 100 / progress.totalBytes FileProvider.getUriForFile(context, "${context.packageName}.provider", apk)
downloadProgress.value?.downloadProgress?.value = mProgress.toInt() else
} Uri.fromFile(apk)
.setOnCancelListener {
downloadProgress.value?.downloadProgress?.value = 0
}
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
downloadProgress.value?.downloadProgress?.value = 0
val apk =
File("${context.getExternalFilesDir("manager")?.path}/manager.apk")
val uri =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
FileProvider.getUriForFile(
context,
"${context.packageName}.provider",
apk
)
else
Uri.fromFile(apk)
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "application/vnd.android.package-archive") intent.setDataAndType(uri, "application/vnd.android.package-archive")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.startActivity(intent) context.startActivity(intent)
sendCloseDialog(context) sendCloseDialog(context)
} }, onError = {
downloadProgress.value?.downloadingFile?.postValue(context.getString(R.string.error_downloading, "manager.apk"))
})
}
override fun onError(error: com.downloader.Error?) {
Toast.makeText(context, error.toString(), Toast.LENGTH_SHORT).show()
Log.e("VMUpgrade", error.toString())
}
})
}
} }

View File

@ -32,8 +32,6 @@ object InternetTools {
var vancedVersions = ObservableField<JsonArray<String>>() var vancedVersions = ObservableField<JsonArray<String>>()
var musicVersions = ObservableField<JsonArray<String>>() var musicVersions = ObservableField<JsonArray<String>>()
const val backupUrl = "https://mirror.codebucket.de/vanced/api/v1"
//var braveTiers = ObservableField<JsonObject?>() //var braveTiers = ObservableField<JsonObject?>()
fun openUrl(url: String, color: Int, context: Context) { fun openUrl(url: String, color: Int, context: Context) {
@ -80,7 +78,7 @@ object InternetTools {
} }
suspend fun getJsonString(file: String, obj: String, context: Context): String { private suspend fun getJsonString(file: String, obj: String, context: Context): String {
val installUrl = context.getDefaultPrefs().getString("install_url", baseUrl) val installUrl = context.getDefaultPrefs().getString("install_url", baseUrl)
return try { return try {
JsonHelper.getJson("$installUrl/$file")?.string(obj) ?: context.getString(R.string.unavailable) JsonHelper.getJson("$installUrl/$file")?.string(obj) ?: context.getString(R.string.unavailable)
@ -91,9 +89,11 @@ object InternetTools {
} }
fun isUpdateAvailable(): Boolean { fun isUpdateAvailable(): Boolean {
val result = manager.get()?.int("versionCode") ?: 0 while (true) {
if (manager.get() != null) {
return result > BuildConfig.VERSION_CODE return manager.get()?.int("versionCode") ?: 0 > BuildConfig.VERSION_CODE
}
}
} }
suspend fun getSha256(hashUrl: String, obj: String, context: Context): String { suspend fun getSha256(hashUrl: String, obj: String, context: Context): String {