fix(installer): sign and install on threads

This is needed to avoid ANRs because it takes a while if the Apk is 100+
MB.
This commit is contained in:
Ax333l 2023-07-07 12:31:31 +02:00
parent d611ae7e9c
commit a09e00c7a9
No known key found for this signature in database
GPG Key ID: D2B4D85271127D23
3 changed files with 22 additions and 11 deletions

View File

@ -15,6 +15,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import androidx.work.WorkInfo
import androidx.work.WorkManager
import app.revanced.manager.domain.manager.KeystoreManager
@ -32,8 +33,11 @@ import app.revanced.manager.util.toast
import app.revanced.patcher.logging.Logger
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import java.io.File
@ -146,10 +150,12 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
signedFile.delete()
}
private fun signApk(): Boolean {
private suspend fun signApk(): Boolean {
if (!hasSigned) {
try {
keystoreManager.sign(outputFile, signedFile)
withContext(Dispatchers.Default) {
keystoreManager.sign(outputFile, signedFile)
}
} catch (e: Exception) {
Log.e(tag, "Got exception while signing", e)
app.toast(app.getString(R.string.sign_fail, e::class.simpleName))
@ -160,22 +166,27 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
return true
}
fun export(uri: Uri?) = uri?.let {
if (signApk()) {
Files.copy(signedFile.toPath(), app.contentResolver.openOutputStream(it))
app.toast(app.getString(R.string.export_app_success))
fun export(uri: Uri?) = viewModelScope.launch {
uri?.let {
if (signApk()) {
withContext(Dispatchers.IO) {
app.contentResolver.openOutputStream(it)
.use { stream -> Files.copy(signedFile.toPath(), stream) }
}
app.toast(app.getString(R.string.export_app_success))
}
}
}
fun installOrOpen() {
fun installOrOpen() = viewModelScope.launch {
installedPackageName?.let {
pm.launch(it)
return
return@launch
}
isInstalling = true
try {
if (!signApk()) return
if (!signApk()) return@launch
pm.installApp(listOf(signedFile))
} finally {
isInstalling = false

View File

@ -39,7 +39,7 @@ class UpdateProgressViewModel(
}
}
fun installUpdate() {
fun installUpdate() = viewModelScope.launch {
pm.installApp(listOf(location))
}

View File

@ -107,7 +107,7 @@ class PM(
})
}
fun installApp(apks: List<File>) {
suspend fun installApp(apks: List<File>) = withContext(Dispatchers.IO) {
val packageInstaller = app.packageManager.packageInstaller
packageInstaller.openSession(packageInstaller.createSession(sessionParams)).use { session ->
apks.forEach { apk -> session.writeApk(apk) }