diff --git a/app/src/main/kotlin/com/aliucord/manager/ManagerApplication.kt b/app/src/main/kotlin/com/aliucord/manager/ManagerApplication.kt index 9b8a829..d32a7c5 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ManagerApplication.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ManagerApplication.kt @@ -70,7 +70,6 @@ class ManagerApplication : Application() { singleOf(::InstallerManager) singleOf(::OverlayManager) - singleOf(::DownloadManagerProvider) singleOf(::AndroidDownloadManager) singleOf(::KtorDownloadManager) }) diff --git a/app/src/main/kotlin/com/aliucord/manager/di/DownloadManagerProvider.kt b/app/src/main/kotlin/com/aliucord/manager/di/DownloadManagerProvider.kt deleted file mode 100644 index 21c6efe..0000000 --- a/app/src/main/kotlin/com/aliucord/manager/di/DownloadManagerProvider.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.aliucord.manager.di - -import com.aliucord.manager.manager.PreferencesManager -import com.aliucord.manager.manager.download.* -import com.aliucord.manager.patcher.util.Signer.getKoin -import com.aliucord.manager.util.IS_PROBABLY_EMULATOR -import org.koin.core.annotation.KoinInternalApi -import kotlin.reflect.KClass - -/** - * Handle providing the correct install manager based on preferences and device type. - */ -class DownloadManagerProvider(private val prefs: PreferencesManager) { - fun getActiveDownloader(): IDownloadManager = - getDownloader(prefs.downloader) - - @OptIn(KoinInternalApi::class) - fun getDownloader(type: DownloaderSetting): IDownloadManager = - getKoin().scopeRegistry.rootScope.get(clazz = type.downloaderClass) - - companion object { - fun getDefaultDownloader(): DownloaderSetting { - // Ktor downloader has specific fix for emulator - return if (IS_PROBABLY_EMULATOR) { - DownloaderSetting.Ktor - } else { - DownloaderSetting.Android - } - } - } -} - -enum class DownloaderSetting( - // @StringRes - // private val localizedName: Int, - val downloaderClass: KClass, -) { - Android(AndroidDownloadManager::class), - Ktor(KtorDownloadManager::class), -} diff --git a/app/src/main/kotlin/com/aliucord/manager/manager/PathManager.kt b/app/src/main/kotlin/com/aliucord/manager/manager/PathManager.kt index 498cb8e..19a3a62 100644 --- a/app/src/main/kotlin/com/aliucord/manager/manager/PathManager.kt +++ b/app/src/main/kotlin/com/aliucord/manager/manager/PathManager.kt @@ -37,7 +37,7 @@ class PathManager( * Use the external cache directory (`/storage/emulated/0/Android/data/com.aliucord.manager/cache`) * when dev mode or preserving APKs is enabled. Otherwise, default to internal app cache. */ - private val externalCacheDir + private val cacheDir get() = when (prefs.devMode || prefs.keepPatchedApks) { false -> context.cacheDir true -> context.externalCacheDir @@ -48,16 +48,16 @@ class PathManager( * Delete the entire cache dir and recreate it. */ fun clearCache() { - if (!externalCacheDir.deleteRecursively()) + if (!cacheDir.deleteRecursively()) throw IllegalStateException("Failed to delete cache") - externalCacheDir.mkdirs() + cacheDir.mkdirs() } /** * Create a new subfolder in the Discord APK cache for a specific version. */ - fun discordApkVersionCache(version: Int): File = externalCacheDir + fun discordApkVersionCache(version: Int): File = cacheDir .resolve("discord") .resolve(version.toString()) .apply { mkdirs() } @@ -65,45 +65,45 @@ class PathManager( /** * Resolve a specific path for a cached injector. */ - fun cachedInjectorDex(version: SemVer, custom: Boolean = false) = externalCacheDir + fun cachedInjectorDex(version: SemVer, custom: Boolean = false) = cacheDir .resolve("injector").apply { mkdirs() } .resolve("$version${if (custom) ".custom" else ""}.dex") /** * Get all the versions of custom injector builds. */ - fun customInjectorDexs() = listCustomFiles(externalCacheDir.resolve("injector")) + fun customInjectorDexs() = listCustomFiles(cacheDir.resolve("injector")) /** * Resolve a specific path for a versioned cached Aliuhook build */ - fun cachedAliuhookAAR(version: SemVer) = externalCacheDir + fun cachedAliuhookAAR(version: SemVer) = cacheDir .resolve("aliuhook").apply { mkdirs() } .resolve("$version.aar") /** * Resolve a specific path for a versioned smali patches archive. */ - fun cachedSmaliPatches(version: SemVer, custom: Boolean = false) = externalCacheDir + fun cachedSmaliPatches(version: SemVer, custom: Boolean = false) = cacheDir .resolve("patches").apply { mkdirs() } .resolve("$version${if (custom) ".custom" else ""}.zip") /** * Get all the versions of custom smali bundles. */ - fun customSmaliPatches() = listCustomFiles(externalCacheDir.resolve("patches")) + fun customSmaliPatches() = listCustomFiles(cacheDir.resolve("patches")) /** * Singular Kotlin file of the most up-to-date version * since the stdlib is backwards compatible. */ - fun cachedKotlinDex() = externalCacheDir + fun cachedKotlinDex() = cacheDir .resolve("kotlin.dex") /** * The temporary working directory of a currently executing patching process. */ - fun patchingWorkingDir() = externalCacheDir + fun patchingWorkingDir() = cacheDir .resolve("patched") private companion object { diff --git a/app/src/main/kotlin/com/aliucord/manager/manager/PreferencesManager.kt b/app/src/main/kotlin/com/aliucord/manager/manager/PreferencesManager.kt index 639b781..ba70699 100644 --- a/app/src/main/kotlin/com/aliucord/manager/manager/PreferencesManager.kt +++ b/app/src/main/kotlin/com/aliucord/manager/manager/PreferencesManager.kt @@ -1,8 +1,6 @@ package com.aliucord.manager.manager import android.content.SharedPreferences -import com.aliucord.manager.di.DownloadManagerProvider -import com.aliucord.manager.di.DownloaderSetting import com.aliucord.manager.manager.base.BasePreferenceManager import com.aliucord.manager.ui.components.Theme @@ -10,7 +8,6 @@ class PreferencesManager(preferences: SharedPreferences) : BasePreferenceManager var theme by enumPreference("theme", Theme.DARK) var dynamicColor by booleanPreference("dynamic_color", false) var devMode by booleanPreference("dev_mode", false) - var downloader by enumPreference("downloader", DownloadManagerProvider.getDefaultDownloader()) var installer by enumPreference("installer", InstallerSetting.PM) var keepPatchedApks by booleanPreference("keep_patched_apks", false) } diff --git a/app/src/main/kotlin/com/aliucord/manager/manager/download/AndroidDownloadManager.kt b/app/src/main/kotlin/com/aliucord/manager/manager/download/AndroidDownloadManager.kt index 6ea6726..94fb495 100644 --- a/app/src/main/kotlin/com/aliucord/manager/manager/download/AndroidDownloadManager.kt +++ b/app/src/main/kotlin/com/aliucord/manager/manager/download/AndroidDownloadManager.kt @@ -6,6 +6,7 @@ import android.content.Context import android.database.Cursor import android.net.Uri import androidx.core.content.getSystemService +import androidx.core.net.toUri import com.aliucord.manager.BuildConfig import com.aliucord.manager.R import com.aliucord.manager.manager.download.IDownloadManager.ProgressListener @@ -34,7 +35,7 @@ class AndroidDownloadManager(application: Application) : IDownloadManager { out.parentFile?.mkdirs() // Create and start a download in the system DownloadManager - val downloadId = DownloadManager.Request(Uri.parse(url)) + val downloadId = DownloadManager.Request(url.toUri()) .setTitle("Aliucord Manager") .setDescription("Downloading ${out.name}...") .setDestinationUri(Uri.fromFile(out)) diff --git a/app/src/main/kotlin/com/aliucord/manager/manager/download/KtorDownloadManager.kt b/app/src/main/kotlin/com/aliucord/manager/manager/download/KtorDownloadManager.kt index 8d9824d..8bde805 100644 --- a/app/src/main/kotlin/com/aliucord/manager/manager/download/KtorDownloadManager.kt +++ b/app/src/main/kotlin/com/aliucord/manager/manager/download/KtorDownloadManager.kt @@ -1,6 +1,7 @@ package com.aliucord.manager.manager.download import com.aliucord.manager.manager.download.IDownloadManager.Result +import com.aliucord.manager.util.IS_PROBABLY_EMULATOR import io.ktor.client.HttpClient import io.ktor.client.request.header import io.ktor.client.request.prepareGet @@ -28,7 +29,9 @@ class KtorDownloadManager(private val http: HttpClient) : IDownloadManager { val httpStmt = http.prepareGet(url) { // Disable compression due to bug on emulators // This header cannot be set with Android's DownloadManager - header(HttpHeaders.AcceptEncoding, null) + if (IS_PROBABLY_EMULATOR) { + header(HttpHeaders.AcceptEncoding, null) + } } httpStmt.execute { resp -> diff --git a/app/src/main/kotlin/com/aliucord/manager/patcher/steps/base/DownloadStep.kt b/app/src/main/kotlin/com/aliucord/manager/patcher/steps/base/DownloadStep.kt index 8922acd..c0225e4 100644 --- a/app/src/main/kotlin/com/aliucord/manager/patcher/steps/base/DownloadStep.kt +++ b/app/src/main/kotlin/com/aliucord/manager/patcher/steps/base/DownloadStep.kt @@ -1,22 +1,14 @@ package com.aliucord.manager.patcher.steps.base -import android.app.DownloadManager import android.content.Context -import android.util.Log import android.widget.Toast import androidx.annotation.CallSuper import androidx.compose.runtime.Stable -import com.aliucord.manager.BuildConfig import com.aliucord.manager.R -import com.aliucord.manager.di.DownloadManagerProvider -import com.aliucord.manager.di.DownloaderSetting -import com.aliucord.manager.manager.OverlayManager -import com.aliucord.manager.manager.PreferencesManager -import com.aliucord.manager.manager.download.AndroidDownloadManager import com.aliucord.manager.manager.download.IDownloadManager +import com.aliucord.manager.manager.download.KtorDownloadManager import com.aliucord.manager.patcher.StepRunner import com.aliucord.manager.patcher.steps.StepGroup -import com.aliucord.manager.ui.components.dialogs.AlternativeDownloaderDialog import com.aliucord.manager.util.showToast import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -27,9 +19,7 @@ import java.io.File @Stable abstract class DownloadStep : Step(), KoinComponent { private val context: Context by inject() - private val overlays: OverlayManager by inject() - private val prefs: PreferencesManager by inject() - private val downloaders: DownloadManagerProvider by inject() + private val downloader: KtorDownloadManager by inject() /** * The remote url to download @@ -67,7 +57,7 @@ abstract class DownloadStep : Step(), KoinComponent { targetFile.delete() } - val result = downloaders.getActiveDownloader().download(targetUrl, targetFile) { newProgress -> + val result = downloader.download(targetUrl, targetFile) { newProgress -> progress = newProgress ?: -1f } @@ -96,29 +86,6 @@ abstract class DownloadStep : Step(), KoinComponent { Toast.makeText(context, toastText, Toast.LENGTH_LONG).show() } - // If this is a specific Android DownloadManager error, then prompt to use a different downloader - if (result is AndroidDownloadManager.Error - && result.reason in arrayOf(DownloadManager.ERROR_HTTP_DATA_ERROR, DownloadManager.ERROR_CANNOT_RESUME) - && prefs.downloader != DownloaderSetting.Ktor - ) { - state = StepState.Error - - val confirmed = overlays.startComposableForResult { callback -> - AlternativeDownloaderDialog( - onConfirm = { callback(true) }, - onDismiss = { callback(false) }, - ) - } - - if (confirmed) { - Log.i(BuildConfig.TAG, "Changing to alternative downloader after failure") - prefs.downloader = DownloaderSetting.Ktor - state = StepState.Running - - return execute(container) - } - } - throw Error("Failed to download: $result") } } diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/AlternativeDownloaderDialog.kt b/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/AlternativeDownloaderDialog.kt deleted file mode 100644 index eee0a8c..0000000 --- a/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/AlternativeDownloaderDialog.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.aliucord.manager.ui.components.dialogs - -import androidx.compose.foundation.layout.size -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import com.aliucord.manager.R - -@Composable -fun AlternativeDownloaderDialog( - onConfirm: () -> Unit, - onDismiss: () -> Unit, -) { - AlertDialog( - onDismissRequest = onDismiss, - confirmButton = { - FilledTonalButton( - onClick = onConfirm, - colors = ButtonDefaults.filledTonalButtonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary, - ), - ) { - Text(stringResource(R.string.action_retry)) - } - }, - dismissButton = { - TextButton( - onClick = onDismiss, - colors = ButtonDefaults.textButtonColors( - contentColor = MaterialTheme.colorScheme.error, - ), - ) { - Text(stringResource(R.string.action_cancel)) - } - }, - title = { Text(stringResource(R.string.alt_downloader_dialog_title)) }, - text = { - Text( - text = stringResource(R.string.alt_downloader_dialog_desc), - textAlign = TextAlign.Center, - ) - }, - icon = { - Icon( - painter = painterResource(R.drawable.ic_download), - contentDescription = null, - modifier = Modifier.size(32.dp), - ) - }, - ) -} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsScreen.kt index 6d93cee..9ba153c 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.koin.getScreenModel import com.aliucord.manager.R -import com.aliucord.manager.di.DownloaderSetting import com.aliucord.manager.ui.components.BackButton import com.aliucord.manager.ui.components.settings.* import com.aliucord.manager.ui.screens.settings.components.ThemeDialog @@ -102,20 +101,6 @@ class SettingsScreen : Screen, Parcelable { onPrefChange = { preferences.keepPatchedApks = it }, ) - SettingsSwitch( - label = stringResource(R.string.setting_alt_downloader), - secondaryLabel = stringResource(R.string.setting_alt_downloader_desc), - icon = { Icon(painterResource(R.drawable.ic_download), null) }, - pref = preferences.downloader == DownloaderSetting.Ktor, - onPrefChange = { - preferences.downloader = if (it) { - DownloaderSetting.Ktor - } else { - DownloaderSetting.Android - } - } - ) - var clearedCache by rememberSaveable { mutableStateOf(false) } Button( shape = ShapeDefaults.Large, diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/widgets/updater/UpdaterViewModel.kt b/app/src/main/kotlin/com/aliucord/manager/ui/widgets/updater/UpdaterViewModel.kt index 9313155..fd379c6 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/widgets/updater/UpdaterViewModel.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/widgets/updater/UpdaterViewModel.kt @@ -5,10 +5,10 @@ import androidx.compose.runtime.* import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.aliucord.manager.BuildConfig -import com.aliucord.manager.di.DownloadManagerProvider import com.aliucord.manager.domain.repository.GithubRepository import com.aliucord.manager.manager.InstallerManager import com.aliucord.manager.manager.InstallerSetting +import com.aliucord.manager.manager.download.KtorDownloadManager import com.aliucord.manager.network.utils.SemVer import com.aliucord.manager.network.utils.getOrNull import kotlinx.coroutines.Dispatchers @@ -16,7 +16,7 @@ import kotlinx.coroutines.launch class UpdaterViewModel( private val github: GithubRepository, - private val downloaders: DownloadManagerProvider, + private val downloader: KtorDownloadManager, private val installers: InstallerManager, private val application: Application, ) : ViewModel() { @@ -40,17 +40,15 @@ class UpdaterViewModel( viewModelScope.launch { isWorking = true - application.externalCacheDir!!.resolve("manager.apk").also { - it.delete() + val apkFile = application.cacheDir.resolve("manager.apk").apply { delete() } - downloaders.getActiveDownloader().download(url, it) - installers.getInstaller(InstallerSetting.PM).install( - apks = listOf(it), - silent = true, - ) + downloader.download(url, apkFile) + installers.getInstaller(InstallerSetting.PM).install( + apks = listOf(apkFile), + silent = true, + ) - it.delete() - } + apkFile.delete() } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a9708b5..68d0973 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -49,8 +49,6 @@ Enables Material You theming on Android 12+ Keep patched APKs Keep all patched files and APKs after installing for debugging. - Alternative downloader - Use a custom HTTP client instead of the system DownloadManager. May fix download errors on specific devices. System Dark @@ -171,9 +169,6 @@ Continue Open Play Protect - Alternative Downloader - This download failed with a specific error that may indicate issues with the system\'s DownloadManager. Would you like to retry with the the alternative downloader implementation? - Fun Fact: %s Did you know that Google Play Protect is useless? Did you know Aliucord with 150+ plugins somehow runs better than Discord\'s new app?