diff --git a/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json b/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json index 543d7a70..041d1dea 100644 --- a/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json +++ b/app/schemas/app.revanced.manager.data.room.AppDatabase/1.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "5515d164bc8f713201506d42a02d337f", + "identityHash": "371c7a84b122a2de8b660b35e6e9ce14", "entities": [ { "tableName": "patch_bundles", @@ -160,7 +160,7 @@ }, { "tableName": "downloaded_app", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `version` TEXT NOT NULL, `file` TEXT NOT NULL, PRIMARY KEY(`package_name`, `version`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `version` TEXT NOT NULL, `directory` TEXT NOT NULL, PRIMARY KEY(`package_name`, `version`))", "fields": [ { "fieldPath": "packageName", @@ -175,8 +175,8 @@ "notNull": true }, { - "fieldPath": "file", - "columnName": "file", + "fieldPath": "directory", + "columnName": "directory", "affinity": "TEXT", "notNull": true } @@ -300,7 +300,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5515d164bc8f713201506d42a02d337f')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '371c7a84b122a2de8b660b35e6e9ce14')" ] } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/data/room/Converters.kt b/app/src/main/java/app/revanced/manager/data/room/Converters.kt index f8aa073d..7de50382 100644 --- a/app/src/main/java/app/revanced/manager/data/room/Converters.kt +++ b/app/src/main/java/app/revanced/manager/data/room/Converters.kt @@ -16,5 +16,5 @@ class Converters { fun fileFromString(value: String) = File(value) @TypeConverter - fun fileToString(file: File): String = file.absolutePath + fun fileToString(file: File): String = file.path } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/data/room/apps/downloaded/DownloadedApp.kt b/app/src/main/java/app/revanced/manager/data/room/apps/downloaded/DownloadedApp.kt index a30063ff..60d1561d 100644 --- a/app/src/main/java/app/revanced/manager/data/room/apps/downloaded/DownloadedApp.kt +++ b/app/src/main/java/app/revanced/manager/data/room/apps/downloaded/DownloadedApp.kt @@ -11,5 +11,5 @@ import java.io.File data class DownloadedApp( @ColumnInfo(name = "package_name") val packageName: String, @ColumnInfo(name = "version") val version: String, - @ColumnInfo(name = "file") val file: File, + @ColumnInfo(name = "directory") val directory: File, ) \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/domain/repository/DownloadedAppRepository.kt b/app/src/main/java/app/revanced/manager/domain/repository/DownloadedAppRepository.kt index 7035c6c4..fe339a2e 100644 --- a/app/src/main/java/app/revanced/manager/domain/repository/DownloadedAppRepository.kt +++ b/app/src/main/java/app/revanced/manager/domain/repository/DownloadedAppRepository.kt @@ -1,34 +1,61 @@ package app.revanced.manager.domain.repository +import android.app.Application +import android.content.Context import app.revanced.manager.data.room.AppDatabase +import app.revanced.manager.data.room.AppDatabase.Companion.generateUid import app.revanced.manager.data.room.apps.downloaded.DownloadedApp +import app.revanced.manager.network.downloader.AppDownloader import kotlinx.coroutines.flow.distinctUntilChanged import java.io.File class DownloadedAppRepository( + app: Application, db: AppDatabase ) { + private val dir = app.getDir("downloaded-apps", Context.MODE_PRIVATE) private val dao = db.downloadedAppDao() fun getAll() = dao.getAllApps().distinctUntilChanged() - suspend fun get(packageName: String, version: String) = dao.get(packageName, version) + fun getApkFileForApp(app: DownloadedApp): File = getApkFileForDir(dir.resolve(app.directory)) + private fun getApkFileForDir(directory: File) = directory.listFiles()!!.first() - suspend fun add( - packageName: String, - version: String, - file: File - ) = dao.insert( - DownloadedApp( - packageName = packageName, - version = version, - file = file - ) - ) + suspend fun download( + app: AppDownloader.App, + preferSplits: Boolean, + onDownload: suspend (downloadProgress: Pair?) -> Unit = {}, + ): File { + this.get(app.packageName, app.version)?.let { downloaded -> + return getApkFileForApp(downloaded) + } + + // Converted integers cannot contain / or .. unlike the package name or version, so they are safer to use here. + val relativePath = File(generateUid().toString()) + val savePath = dir.resolve(relativePath).also { it.mkdirs() } + + try { + app.download(savePath, preferSplits, onDownload) + + dao.insert(DownloadedApp( + packageName = app.packageName, + version = app.version, + directory = relativePath, + )) + } catch (e: Exception) { + savePath.deleteRecursively() + throw e + } + + // Return the Apk file. + return getApkFileForDir(savePath) + } + + suspend fun get(packageName: String, version: String) = dao.get(packageName, version) suspend fun delete(downloadedApps: Collection) { downloadedApps.forEach { - it.file.deleteRecursively() + dir.resolve(it.directory).deleteRecursively() } dao.delete(downloadedApps) diff --git a/app/src/main/java/app/revanced/manager/network/downloader/APKMirror.kt b/app/src/main/java/app/revanced/manager/network/downloader/APKMirror.kt index 3a055ef5..30c6fbee 100644 --- a/app/src/main/java/app/revanced/manager/network/downloader/APKMirror.kt +++ b/app/src/main/java/app/revanced/manager/network/downloader/APKMirror.kt @@ -171,7 +171,7 @@ class APKMirror : AppDownloader, KoinComponent { saveDirectory: File, preferSplit: Boolean, onDownload: suspend (downloadProgress: Pair?) -> Unit - ): File { + ) { val variants = httpClient.getHtml { url(apkMirror + downloadLink) } .div { withClass = "variants-table" @@ -246,18 +246,10 @@ class APKMirror : AppDownloader, KoinComponent { } } - val saveLocation = if (variant.apkType == APKType.BUNDLE) - saveDirectory.resolve(version).also { it.mkdirs() } - else - saveDirectory.resolve("$version.apk") + val targetFile = saveDirectory.resolve("base.apk") try { - val downloadLocation = if (variant.apkType == APKType.BUNDLE) - saveLocation.resolve("temp.zip") - else - saveLocation - - httpClient.download(downloadLocation) { + httpClient.download(targetFile) { url(apkMirror + downloadLink) onDownload { bytesSentTotal, contentLength -> onDownload(bytesSentTotal.div(100000).toFloat().div(10) to contentLength.div(100000).toFloat().div(10)) @@ -267,16 +259,11 @@ class APKMirror : AppDownloader, KoinComponent { if (variant.apkType == APKType.BUNDLE) { // TODO: Extract temp.zip - downloadLocation.delete() + targetFile.delete() } - } catch (e: Exception) { - saveLocation.deleteRecursively() - throw e } finally { onDownload(null) } - - return saveLocation } } diff --git a/app/src/main/java/app/revanced/manager/network/downloader/AppDownloader.kt b/app/src/main/java/app/revanced/manager/network/downloader/AppDownloader.kt index a6a17622..dcefa26e 100644 --- a/app/src/main/java/app/revanced/manager/network/downloader/AppDownloader.kt +++ b/app/src/main/java/app/revanced/manager/network/downloader/AppDownloader.kt @@ -22,7 +22,6 @@ interface AppDownloader { saveDirectory: File, preferSplit: Boolean, onDownload: suspend (downloadProgress: Pair?) -> Unit = {} - ): File + ) } - } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt b/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt index 864eb343..b6a33637 100644 --- a/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt +++ b/app/src/main/java/app/revanced/manager/patcher/worker/PatcherWorker.kt @@ -190,19 +190,11 @@ class PatcherWorker( val inputFile = when (val selectedApp = args.input) { is SelectedApp.Download -> { - val savePath = applicationContext.filesDir.resolve("downloaded-apps") - .resolve(args.input.packageName).also { it.mkdirs() } - - selectedApp.app.download( - savePath, + downloadedAppRepository.download( + selectedApp.app, prefs.preferSplits.get(), onDownload = { downloadProgress.emit(it) } ).also { - downloadedAppRepository.add( - args.input.packageName, - args.input.version, - it - ) args.setInputFile(it) updateProgress() // Downloading } diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/VersionSelectorViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/VersionSelectorViewModel.kt index f7420131..cae25116 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/VersionSelectorViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/VersionSelectorViewModel.kt @@ -68,7 +68,7 @@ class VersionSelectorViewModel( } val downloadedVersions = downloadedAppRepository.getAll().map { downloadedApps -> - downloadedApps.filter { it.packageName == packageName }.map { SelectedApp.Local(it.packageName, it.version, it.file, false) } + downloadedApps.filter { it.packageName == packageName }.map { SelectedApp.Local(it.packageName, it.version, downloadedAppRepository.getApkFileForApp(it), false) } } init {