mirror of
https://github.com/revanced/revanced-manager
synced 2024-05-14 13:56:57 +02:00
refactor(downloaders): improve file system code (#1379)
This commit is contained in:
parent
56a4a7043d
commit
8f6d720454
@ -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')"
|
||||
]
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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,
|
||||
)
|
@ -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<Float, Float>?) -> 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<DownloadedApp>) {
|
||||
downloadedApps.forEach {
|
||||
it.file.deleteRecursively()
|
||||
dir.resolve(it.directory).deleteRecursively()
|
||||
}
|
||||
|
||||
dao.delete(downloadedApps)
|
||||
|
@ -171,7 +171,7 @@ class APKMirror : AppDownloader, KoinComponent {
|
||||
saveDirectory: File,
|
||||
preferSplit: Boolean,
|
||||
onDownload: suspend (downloadProgress: Pair<Float, Float>?) -> 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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ interface AppDownloader {
|
||||
saveDirectory: File,
|
||||
preferSplit: Boolean,
|
||||
onDownload: suspend (downloadProgress: Pair<Float, Float>?) -> Unit = {}
|
||||
): File
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user