diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 55d494f..bd58672 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -86,6 +86,7 @@ dependencies {
val koinVersion = "3.2.0"
implementation("io.insert-koin:koin-android:$koinVersion")
implementation("io.insert-koin:koin-androidx-compose:$koinVersion")
+ implementation("io.insert-koin:koin-androidx-workmanager:3.2.1")
// Compose
val composeVersion = "1.3.0-alpha03"
@@ -117,7 +118,7 @@ dependencies {
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
// ReVanced
- implementation("app.revanced:revanced-patcher:4.2.3")
+ implementation("app.revanced:revanced-patcher:4.4.2")
// Coil for network image
implementation("io.coil-kt:coil-compose:2.1.0")
@@ -125,4 +126,5 @@ dependencies {
// Signing & aligning
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
implementation("com.android.tools.build:apksig:7.2.2")
+
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 129d5e8..1194e75 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -33,8 +33,19 @@
android:supportsRtl="true"
android:largeHeap="true"
android:theme="@style/Theme.ReVancedManager"
-
tools:targetApi="33">
+
+
+
+
+
when (destination) {
is AppDestination.Dashboard -> MainDashboardScreen(navigator = navigator)
- is AppDestination.AppSelector -> AppSelectorSubscreen(
- navigator = navigator
- )
+ is AppDestination.AppSelector -> AppSelectorSubscreen(navigator = navigator)
is AppDestination.PatchSelector -> PatchesSelectorSubscreen(navigator = navigator)
+ is AppDestination.Patcher -> PatchingScreen(navigator = navigator)
}
}
}
diff --git a/app/src/main/java/app/revanced/manager/ManagerApplication.kt b/app/src/main/java/app/revanced/manager/ManagerApplication.kt
index eacc2aa..75368bf 100644
--- a/app/src/main/java/app/revanced/manager/ManagerApplication.kt
+++ b/app/src/main/java/app/revanced/manager/ManagerApplication.kt
@@ -1,11 +1,9 @@
package app.revanced.manager
import android.app.Application
-import app.revanced.manager.di.httpModule
-import app.revanced.manager.di.preferencesModule
-import app.revanced.manager.di.repositoryModule
-import app.revanced.manager.di.viewModelModule
+import app.revanced.manager.di.*
import org.koin.android.ext.koin.androidContext
+import org.koin.androidx.workmanager.koin.workManagerFactory
import org.koin.core.context.startKoin
class ManagerApplication : Application() {
@@ -14,7 +12,8 @@ class ManagerApplication : Application() {
startKoin {
androidContext(this@ManagerApplication)
- modules(httpModule, preferencesModule, viewModelModule, repositoryModule)
+ workManagerFactory()
+ modules(httpModule, preferencesModule, viewModelModule, repositoryModule, workerModule)
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/app/revanced/manager/api/API.kt b/app/src/main/java/app/revanced/manager/api/API.kt
index 288b0b0..dada585 100644
--- a/app/src/main/java/app/revanced/manager/api/API.kt
+++ b/app/src/main/java/app/revanced/manager/api/API.kt
@@ -29,7 +29,7 @@ val client = HttpClient(Android) {
class API(private val repository: GitHubRepository, private val prefs: PreferencesManager) {
- private suspend fun findAsset(repo: String, file: String): PatchesAsset {
+ suspend fun findAsset(repo: String, file: String): PatchesAsset {
val release = repository.getLatestRelease(repo)
val asset = release.assets.findAsset(file) ?: throw MissingAssetException()
return PatchesAsset(release, asset)
@@ -47,7 +47,6 @@ class API(private val repository: GitHubRepository, private val prefs: Preferenc
throw Exception("Failed to download patch bundle", e)
}
}
-
suspend fun downloadIntegrations(workdir: File): File {
return try {
val (_, out) = downloadAsset(
@@ -60,7 +59,7 @@ class API(private val repository: GitHubRepository, private val prefs: Preferenc
}
}
- private suspend fun downloadAsset(
+ suspend fun downloadAsset(
workdir: File,
patchesAsset: PatchesAsset
): Pair {
diff --git a/app/src/main/java/app/revanced/manager/di/ViewModelModule.kt b/app/src/main/java/app/revanced/manager/di/ViewModelModule.kt
index 3bc6759..b940a3d 100644
--- a/app/src/main/java/app/revanced/manager/di/ViewModelModule.kt
+++ b/app/src/main/java/app/revanced/manager/di/ViewModelModule.kt
@@ -1,15 +1,13 @@
package app.revanced.manager.di
-import app.revanced.manager.ui.viewmodel.AppSelectorViewModel
-import app.revanced.manager.ui.viewmodel.DashboardViewModel
-import app.revanced.manager.ui.viewmodel.PatcherViewModel
-import app.revanced.manager.ui.viewmodel.SettingsViewModel
+import app.revanced.manager.ui.viewmodel.*
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.dsl.module
val viewModelModule = module {
viewModelOf(::SettingsViewModel)
viewModelOf(::DashboardViewModel)
- viewModelOf(::PatcherViewModel)
+ viewModelOf(::PatcherScreenViewModel)
viewModelOf(::AppSelectorViewModel)
+ viewModelOf(::PatchingScreenViewModel)
}
\ No newline at end of file
diff --git a/app/src/main/java/app/revanced/manager/di/WorkerModule.kt b/app/src/main/java/app/revanced/manager/di/WorkerModule.kt
new file mode 100644
index 0000000..3656012
--- /dev/null
+++ b/app/src/main/java/app/revanced/manager/di/WorkerModule.kt
@@ -0,0 +1,10 @@
+package app.revanced.manager.di
+
+import app.revanced.manager.patcher.worker.PatcherWorker
+import org.koin.android.ext.koin.androidContext
+import org.koin.androidx.workmanager.dsl.worker
+import org.koin.dsl.module
+
+val workerModule = module {
+ worker { PatcherWorker( androidContext(), get(), get())}
+}
\ 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 3a9955f..862aecd 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
@@ -14,13 +14,16 @@ import androidx.work.ForegroundInfo
import androidx.work.WorkerParameters
import app.revanced.manager.R
import app.revanced.manager.Variables.patches
+import app.revanced.manager.Variables.selectedAppPackage
import app.revanced.manager.Variables.selectedPatches
+import app.revanced.manager.api.API
import app.revanced.manager.patcher.aapt.Aapt
import app.revanced.manager.patcher.aligning.ZipAligner
import app.revanced.manager.patcher.aligning.zip.ZipFile
import app.revanced.manager.patcher.aligning.zip.structures.ZipEntry
import app.revanced.manager.patcher.signing.Signer
import app.revanced.manager.ui.Resource
+import app.revanced.manager.ui.viewmodel.Logging
import app.revanced.patcher.Patcher
import app.revanced.patcher.PatcherOptions
import app.revanced.patcher.data.Data
@@ -29,15 +32,19 @@ import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.logging.Logger
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.impl.ResourcePatch
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import org.koin.core.component.KoinComponent
import java.io.File
import java.nio.file.Files
+import java.nio.file.StandardCopyOption
+
+class PatcherWorker(context: Context, parameters: WorkerParameters, private val api: API): CoroutineWorker(context, parameters) ,KoinComponent {
-class PatcherWorker(context: Context, parameters: WorkerParameters) :
- CoroutineWorker(context, parameters) {
val tag = "ReVanced Manager"
- private val workdir = File(inputData.getString("workdir")!!)
-
+ private val workdir = createWorkDir()
override suspend fun doWork(): Result {
+
if (runAttemptCount > 0) {
return Result.failure(
androidx.work.Data.Builder()
@@ -77,32 +84,41 @@ class PatcherWorker(context: Context, parameters: WorkerParameters) :
}
}
- private fun runPatcher(
+ private suspend fun runPatcher(
workdir: File
): Boolean {
val aaptPath = Aapt.binary(applicationContext).absolutePath
val frameworkPath =
applicationContext.filesDir.resolve("framework").also { it.mkdirs() }.absolutePath
+ val integrationsCacheDir =
+ applicationContext.filesDir.resolve("integrations-cache").also { it.mkdirs() }
+ val appInfo = applicationContext.packageManager.getApplicationInfo(selectedAppPackage.value.get(), 3)
- Log.d(tag, "Checking prerequisites")
+ Logging.log += "Checking prerequisites\n"
val patches = findPatchesByIds(selectedPatches)
if (patches.isEmpty()) return true
- Log.d(tag, "Creating directories")
-
- File(inputData.getString("input")!!).copyTo(
- applicationContext.filesDir.resolve("base.apk"),
- true
- )
-
- val inputFile = File(applicationContext.filesDir, "base.apk")
+ Logging.log += "Creating directories\n"
+ val inputFile = File(applicationContext.filesDir, "input.apk")
val patchedFile = File(workdir, "patched.apk")
- val outputFile = File(applicationContext.filesDir, "out.apk")
+ val outputFile = File(applicationContext.filesDir, "output.apk")
val cacheDirectory = workdir.resolve("cache")
- val integrations = workdir.resolve("integrations.apk")
+
+ Logging.log += "Downloading integrations\n"
+ val integrations = api.downloadIntegrations(integrationsCacheDir)
+
+ Logging.log += "Copying base.apk from device\n"
+ withContext(Dispatchers.IO) {
+ Files.copy(
+ File(appInfo.publicSourceDir).toPath(),
+ inputFile.toPath(),
+ StandardCopyOption.REPLACE_EXISTING
+ )
+ }
+
try {
- Log.d(tag, "Creating patcher")
+ Logging.log += "Decoding resources\n"
val patcher = Patcher( // start patcher
PatcherOptions(
inputFile,
@@ -134,37 +150,42 @@ class PatcherWorker(context: Context, parameters: WorkerParameters) :
Log.d(tag, "Adding ${patches.size} patch(es)")
patcher.addPatches(patches)
+ Logging.log += "Merging integrations\n"
patcher.addFiles(listOf(integrations)) {}
patcher.applyPatches().forEach { (patch, result) ->
+ Logging.log += "Applying $patch\n"
if (result.isSuccess) {
- Log.i(tag, "[success] $patch")
+ Logging.log += "$patch has been applied successfully\n"
return@forEach
}
- Log.e(tag, "[error] $patch:", result.exceptionOrNull()!!)
+ Logging.log += "Failed to apply $patch \n" + result.exceptionOrNull()!!
}
- Log.d(tag, "Saving file")
+ Logging.log += "Saving file\n"
val result = patcher.save() // compile apk
- if (patchedFile.exists()) Files.delete(patchedFile.toPath())
+ if (patchedFile.exists()) withContext(Dispatchers.IO) {
+ Files.delete(patchedFile.toPath())
+ }
ZipFile(patchedFile).use { fs -> // somehow this function is the most resource intensive
- result.dexFiles.forEach { Log.d(tag, "Writing dex file ${it.name}")
+ result.dexFiles.forEach { Logging.log += "Writing dex file ${it.name}\n"
fs.addEntryCompressData(ZipEntry.createWithName(it.name), it.stream.readBytes())}
-
+ Logging.log += "Aligning apk!\n"
result.resourceFile?.let {
fs.copyEntriesFromFileAligned(ZipFile(it), ZipAligner::getEntryAlignment)
}
fs.copyEntriesFromFileAligned(ZipFile(inputFile), ZipAligner::getEntryAlignment)
}
+ Logging.log += "Signing apk\n"
Signer("ReVanced", "s3cur3p@ssw0rd").signApk(patchedFile, outputFile)
- Log.i(tag, "Successfully patched into $outputFile")
+ Logging.log += "Successfully patched!\n"
} finally {
Log.d(tag, "Deleting workdir")
- // workdir.deleteRecursively()
+ workdir.deleteRecursively()
}
return false
}
@@ -187,4 +208,8 @@ class PatcherWorker(context: Context, parameters: WorkerParameters) :
}
return false
}
+ private fun createWorkDir(): File {
+ return applicationContext.filesDir.resolve("tmp-${System.currentTimeMillis()}")
+ .also { it.mkdirs() }
+ }
}
diff --git a/app/src/main/java/app/revanced/manager/ui/component/PatchCompatibilityDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/PatchCompatibilityDialog.kt
index 46a12b9..3746f54 100644
--- a/app/src/main/java/app/revanced/manager/ui/component/PatchCompatibilityDialog.kt
+++ b/app/src/main/java/app/revanced/manager/ui/component/PatchCompatibilityDialog.kt
@@ -10,14 +10,14 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.ui.viewmodel.PatchClass
-import app.revanced.manager.ui.viewmodel.PatcherViewModel
+import app.revanced.manager.ui.viewmodel.PatcherScreenViewModel
import app.revanced.patcher.annotation.Package
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import org.koin.androidx.compose.getViewModel
@Composable
fun PatchCompatibilityDialog(
- patchClass: PatchClass, pvm: PatcherViewModel = getViewModel(), onClose: () -> Unit
+ patchClass: PatchClass, pvm: PatcherScreenViewModel = getViewModel(), onClose: () -> Unit
) {
val patch = patchClass.patch
val packageName = pvm.getSelectedPackageInfo()?.packageName
diff --git a/app/src/main/java/app/revanced/manager/ui/navigation/AppDestination.kt b/app/src/main/java/app/revanced/manager/ui/navigation/AppDestination.kt
index 20a493c..97a7298 100644
--- a/app/src/main/java/app/revanced/manager/ui/navigation/AppDestination.kt
+++ b/app/src/main/java/app/revanced/manager/ui/navigation/AppDestination.kt
@@ -21,6 +21,9 @@ sealed interface AppDestination : Destination {
@Parcelize
object PatchSelector : AppDestination
+
+ @Parcelize
+ object Patcher : AppDestination
}
@Parcelize
diff --git a/app/src/main/java/app/revanced/manager/ui/screen/MainDashboardScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/MainDashboardScreen.kt
index 8c79b2b..d82fb29 100644
--- a/app/src/main/java/app/revanced/manager/ui/screen/MainDashboardScreen.kt
+++ b/app/src/main/java/app/revanced/manager/ui/screen/MainDashboardScreen.kt
@@ -69,7 +69,8 @@ fun MainDashboardScreen(navigator: BackstackNavigator) {
DashboardDestination.DASHBOARD -> DashboardScreen()
DashboardDestination.PATCHER -> PatcherScreen(
onClickAppSelector = { navigator.push(AppDestination.AppSelector) },
- onClickPatchSelector = { navigator.push(AppDestination.PatchSelector) }
+ onClickPatchSelector = { navigator.push(AppDestination.PatchSelector) },
+ onClickPatch = { navigator.push(AppDestination.Patcher) },
)
DashboardDestination.SETTINGS -> SettingsScreen()
}
diff --git a/app/src/main/java/app/revanced/manager/ui/screen/NewPatcherScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/NewPatcherScreen.kt
index fd1b664..5ef41ce 100644
--- a/app/src/main/java/app/revanced/manager/ui/screen/NewPatcherScreen.kt
+++ b/app/src/main/java/app/revanced/manager/ui/screen/NewPatcherScreen.kt
@@ -16,7 +16,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import app.revanced.manager.ui.viewmodel.PatcherViewModel
+import app.revanced.manager.ui.viewmodel.PatcherScreenViewModel
import org.koin.androidx.compose.getViewModel
@OptIn(ExperimentalMaterial3Api::class)
@@ -24,7 +24,7 @@ import org.koin.androidx.compose.getViewModel
fun NewPatcherScreen(
onClickAppSelector: () -> Unit,
onClickPatchSelector: () -> Unit,
- viewModel: PatcherViewModel = getViewModel()
+ viewModel: PatcherScreenViewModel = getViewModel()
) {
var validBundle = false
Column(
diff --git a/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt
index d2c024a..0296eea 100644
--- a/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt
+++ b/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt
@@ -4,14 +4,12 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Build
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.Variables.patches
@@ -20,7 +18,7 @@ import app.revanced.manager.Variables.selectedPatches
import app.revanced.manager.ui.Resource
import app.revanced.manager.ui.component.FloatingActionButton
import app.revanced.manager.ui.component.SplitAPKDialog
-import app.revanced.manager.ui.viewmodel.PatcherViewModel
+import app.revanced.manager.ui.viewmodel.PatcherScreenViewModel
import org.koin.androidx.compose.getViewModel
@OptIn(ExperimentalMaterial3Api::class)
@@ -28,7 +26,8 @@ import org.koin.androidx.compose.getViewModel
fun PatcherScreen(
onClickAppSelector: () -> Unit,
onClickPatchSelector: () -> Unit,
- viewModel: PatcherViewModel = getViewModel()
+ onClickPatch: () -> Unit,
+ viewModel: PatcherScreenViewModel = getViewModel()
) {
val selectedAmount = selectedPatches.size
val selectedAppPackage by selectedAppPackage
@@ -39,9 +38,7 @@ fun PatcherScreen(
Scaffold(floatingActionButton = {
FloatingActionButton(
enabled = hasAppSelected && viewModel.anyPatchSelected(),
- onClick = {
- if (viewModel.checkSplitApk()) { showDialog = true } else viewModel.startPatcher()
- },
+ onClick = { if (viewModel.checkSplitApk()) { showDialog = true } else onClickPatch()},
icon = { Icon(Icons.Default.Build, contentDescription = "Patch") },
text = { Text(text = "Patch") }
)
@@ -53,7 +50,7 @@ fun PatcherScreen(
.padding(16.dp),
) {
if (showDialog)
- SplitAPKDialog(onDismiss = { showDialog = false }, onConfirm = { viewModel.startPatcher() })
+ SplitAPKDialog(onDismiss = { showDialog = false }, onConfirm = onClickPatch)
Card(
modifier = Modifier
.padding(4.dp)
diff --git a/app/src/main/java/app/revanced/manager/ui/screen/PatchingScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/PatchingScreen.kt
new file mode 100644
index 0000000..4d8601d
--- /dev/null
+++ b/app/src/main/java/app/revanced/manager/ui/screen/PatchingScreen.kt
@@ -0,0 +1,74 @@
+package app.revanced.manager.ui.screen
+
+import androidx.compose.foundation.layout.*
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.material3.*
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import app.revanced.manager.ui.navigation.AppDestination
+import app.revanced.manager.ui.viewmodel.Logging
+import app.revanced.manager.ui.viewmodel.PatchingScreenViewModel
+import com.xinto.taxi.BackstackNavigator
+import org.koin.androidx.compose.getViewModel
+
+
+@Composable
+@OptIn(ExperimentalMaterial3Api::class)
+fun PatchingScreen(
+ navigator: BackstackNavigator,
+ vm: PatchingScreenViewModel = getViewModel()
+) {
+ Scaffold(
+ topBar = {
+ Row {
+ IconButton(onClick = navigator::pop) {
+ Icon(
+ imageVector = Icons.Default.ArrowBack,
+ contentDescription = null
+ )
+ }
+ }
+ }
+ ) { paddingValues ->
+ Column {
+ Column(
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .fillMaxHeight(0.2f)
+ .padding(paddingValues),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+
+ if (vm.patchingInProgress) {
+ CircularProgressIndicator(modifier = Modifier.padding(vertical = 16.dp).size(30.dp))
+ Text(text = "Patching...", fontSize = 30.sp)
+ }
+ }
+ }
+ Column(
+ Modifier
+ .fillMaxWidth()
+ .padding(20.dp)
+ ) {
+ Card {
+ Text(
+ text = Logging.log,
+ modifier = Modifier.padding(horizontal = 20.dp, vertical = 10.dp).fillMaxSize(),
+ fontSize = 20.sp,
+ lineHeight = 35.sp
+ )
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/revanced/manager/ui/screen/subscreens/PatchesSelectorSubscreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/subscreens/PatchesSelectorSubscreen.kt
index d2a26c2..641f333 100644
--- a/app/src/main/java/app/revanced/manager/ui/screen/subscreens/PatchesSelectorSubscreen.kt
+++ b/app/src/main/java/app/revanced/manager/ui/screen/subscreens/PatchesSelectorSubscreen.kt
@@ -23,7 +23,7 @@ import app.revanced.manager.ui.component.PatchCompatibilityDialog
import app.revanced.manager.ui.navigation.AppDestination
import app.revanced.manager.ui.theme.Typography
import app.revanced.manager.ui.viewmodel.PatchClass
-import app.revanced.manager.ui.viewmodel.PatcherViewModel
+import app.revanced.manager.ui.viewmodel.PatcherScreenViewModel
import app.revanced.patcher.extensions.PatchExtensions.description
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.extensions.PatchExtensions.version
@@ -34,7 +34,7 @@ import org.koin.androidx.compose.getViewModel
@Composable
fun PatchesSelectorSubscreen(
navigator: BackstackNavigator,
- pvm: PatcherViewModel = getViewModel(),
+ pvm: PatcherScreenViewModel = getViewModel(),
) {
val patches = rememberSaveable { pvm.getFilteredPatchesAndCheckOptions() }
var query by mutableStateOf("")
diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherScreenViewModel.kt
similarity index 75%
rename from app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt
rename to app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherScreenViewModel.kt
index a92c442..c73c60a 100644
--- a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherViewModel.kt
+++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatcherScreenViewModel.kt
@@ -6,15 +6,10 @@ import android.os.Parcelable
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import androidx.work.ExistingWorkPolicy
-import androidx.work.OneTimeWorkRequest
-import androidx.work.OutOfQuotaPolicy
-import androidx.work.WorkManager
import app.revanced.manager.Variables.patches
import app.revanced.manager.Variables.selectedAppPackage
import app.revanced.manager.Variables.selectedPatches
import app.revanced.manager.api.API
-import app.revanced.manager.patcher.worker.PatcherWorker
import app.revanced.manager.ui.Resource
import app.revanced.patcher.data.Data
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
@@ -24,31 +19,22 @@ import app.revanced.patcher.patch.Patch
import app.revanced.patcher.util.patch.impl.DexPatchBundle
import dalvik.system.DexClassLoader
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
import kotlinx.parcelize.Parcelize
-import java.io.File
-class PatcherViewModel(private val app: Application, private val api: API) : ViewModel() {
- private val workdir = createWorkDir()
+class PatcherScreenViewModel(private val app: Application, private val api: API) : ViewModel() {
private lateinit var patchBundleFile: String
private val tag = "ReVanced Manager"
init {
- runBlocking {
+ viewModelScope.launch {
loadPatches()
- downloadIntegrations()
}
}
-
fun selectPatch(patchId: String, state: Boolean) {
if (state) selectedPatches.add(patchId)
else selectedPatches.remove(patchId)
}
- private suspend fun downloadIntegrations() {
- api.downloadIntegrations(workdir).renameTo(File(workdir,"integrations.apk"))
- }
-
fun selectAllPatches(patchList: List, selectAll: Boolean) {
patchList.forEach { patch ->
val patchId = patch.patch.patchName
@@ -85,6 +71,38 @@ class PatcherViewModel(private val app: Application, private val api: API) : Vie
)
else null
+ fun checkSplitApk(): Boolean {
+ if (getSelectedPackageInfo()!!.applicationInfo!!.metaData!!.getBoolean("com.android.vending.splits.required", false)) {
+ Log.d(tag, "APK is split.")
+ return true
+ }
+ Log.d(tag, "APK is not split.")
+ return false
+ }
+
+ private fun loadPatches() = viewModelScope.launch {
+ try {
+ val file = api.downloadPatchBundle(app.filesDir)
+ patchBundleFile = file.absolutePath
+ loadPatches0(file.absolutePath)
+ } catch (e: Exception) {
+ Log.e("ReVancedManager", "An error occurred while loading patches", e)
+ }
+ }
+
+ private fun loadPatches0(path: String) {
+ val patchClasses = DexPatchBundle(
+ path, DexClassLoader(
+ path,
+ app.codeCacheDir.absolutePath,
+ null,
+ javaClass.classLoader
+ )
+ ).loadPatches()
+ patches.value = Resource.Success(patchClasses)
+ Log.d("ReVanced Manager", "Finished loading patches")
+ }
+
fun getFilteredPatchesAndCheckOptions(): List {
return buildList {
val selected = getSelectedPackageInfo() ?: return@buildList
@@ -108,61 +126,6 @@ class PatcherViewModel(private val app: Application, private val api: API) : Vie
}
}
}
-
- fun checkSplitApk(): Boolean {
- if (getSelectedPackageInfo()!!.applicationInfo!!.metaData!!.getBoolean("com.android.vending.splits.required", false)) {
- Log.d(tag, "APK is split.")
- return true
- }
- Log.d(tag, "APK is not split.")
- return false
- }
-
- private fun loadPatches() = viewModelScope.launch {
- try {
- val file = api.downloadPatchBundle(app.filesDir)
- patchBundleFile = file.absolutePath
- loadPatches0(file.absolutePath)
- } catch (e: Exception) {
- Log.e("ReVancedManager", "An error occurred while loading patches", e)
- }
- }
-
-
- private fun loadPatches0(path: String) {
- val patchClasses = DexPatchBundle(
- path, DexClassLoader(
- path,
- app.codeCacheDir.absolutePath,
- null,
- javaClass.classLoader
- )
- ).loadPatches()
- patches.value = Resource.Success(patchClasses)
- Log.d("ReVanced Manager", "Finished loading patches")
- }
-
- fun startPatcher() {
- WorkManager
- .getInstance(app)
- .enqueueUniqueWork(
- "patching",
- ExistingWorkPolicy.KEEP,
- OneTimeWorkRequest.Builder(PatcherWorker::class.java)
- .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
- .setInputData(
- androidx.work.Data.Builder()
- .putString("workdir", workdir.toString())
- .putString("input",
- getSelectedPackageInfo()?.applicationInfo?.publicSourceDir
- )
- .build()).build()
- )
- }
- private fun createWorkDir(): File {
- return app.filesDir.resolve("tmp-${System.currentTimeMillis()}")
- .also { it.mkdirs() }
- }
}
@Parcelize
diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/PatchingScreenViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatchingScreenViewModel.kt
new file mode 100644
index 0000000..b8f1349
--- /dev/null
+++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/PatchingScreenViewModel.kt
@@ -0,0 +1,46 @@
+package app.revanced.manager.ui.viewmodel
+
+import android.app.Application
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import androidx.work.ExistingWorkPolicy
+import androidx.work.OneTimeWorkRequest
+import androidx.work.OutOfQuotaPolicy
+import androidx.work.WorkManager
+import app.revanced.manager.patcher.worker.PatcherWorker
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+class PatchingScreenViewModel(val app: Application) : ViewModel() {
+
+ var patchingInProgress = true
+
+ init {
+ viewModelScope.launch(Dispatchers.Main) {
+ startPatcher()
+ }
+ }
+
+ private fun startPatcher() {
+ WorkManager
+ .getInstance(app)
+ .enqueueUniqueWork(
+ "patching",
+ ExistingWorkPolicy.KEEP,
+ OneTimeWorkRequest.Builder(PatcherWorker::class.java)
+ .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
+ .setInputData(
+ androidx.work.Data.Builder()
+ .build()
+ ).build()
+ )
+ patchingInProgress = false
+ }
+}
+
+object Logging {
+ var log by mutableStateOf("")
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/revanced/manager/util/Constants.kt b/app/src/main/java/app/revanced/manager/util/Constants.kt
index 3ce234c..2a8b7c8 100644
--- a/app/src/main/java/app/revanced/manager/util/Constants.kt
+++ b/app/src/main/java/app/revanced/manager/util/Constants.kt
@@ -5,4 +5,5 @@ const val ghOrganization = "https://github.com/$team"
const val ghPatches = "$team/revanced-patches"
const val ghPatcher = "$team/revanced-patcher"
const val ghManager = "$team/revanced-manager"
-const val ghIntegrations = "$team/revanced-integrations"
\ No newline at end of file
+const val ghIntegrations = "$team/revanced-integrations"
+const val tag = "ReVanced Manager"
\ No newline at end of file