mirror of
https://github.com/revanced/revanced-manager
synced 2024-05-14 13:56:57 +02:00
feat(installer): sign apk in patcher worker
This commit is contained in:
parent
7d887c73e8
commit
172604fcdb
@ -26,7 +26,12 @@ class Step(
|
|||||||
val state: State = State.WAITING
|
val state: State = State.WAITING
|
||||||
)
|
)
|
||||||
|
|
||||||
class PatcherProgressManager(context: Context, selectedPatches: List<String>, selectedApp: SelectedApp, downloadProgress: StateFlow<Pair<Float, Float>?>) {
|
class PatcherProgressManager(
|
||||||
|
context: Context,
|
||||||
|
selectedPatches: List<String>,
|
||||||
|
selectedApp: SelectedApp,
|
||||||
|
downloadProgress: StateFlow<Pair<Float, Float>?>
|
||||||
|
) {
|
||||||
val steps = generateSteps(context, selectedPatches, selectedApp, downloadProgress)
|
val steps = generateSteps(context, selectedPatches, selectedApp, downloadProgress)
|
||||||
private var currentStep: StepKey? = StepKey(0, 0)
|
private var currentStep: StepKey? = StepKey(0, 0)
|
||||||
|
|
||||||
@ -87,12 +92,20 @@ class PatcherProgressManager(context: Context, selectedPatches: List<String>, se
|
|||||||
selectedPatches.map { SubStep(it) }.toImmutableList()
|
selectedPatches.map { SubStep(it) }.toImmutableList()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun generateSteps(context: Context, selectedPatches: List<String>, selectedApp: SelectedApp, downloadProgress: StateFlow<Pair<Float, Float>?>? = null) = mutableListOf(
|
fun generateSteps(
|
||||||
|
context: Context,
|
||||||
|
selectedPatches: List<String>,
|
||||||
|
selectedApp: SelectedApp,
|
||||||
|
downloadProgress: StateFlow<Pair<Float, Float>?>? = null
|
||||||
|
) = mutableListOf(
|
||||||
Step(
|
Step(
|
||||||
R.string.patcher_step_group_prepare,
|
R.string.patcher_step_group_prepare,
|
||||||
listOfNotNull(
|
listOfNotNull(
|
||||||
SubStep(context.getString(R.string.patcher_step_load_patches)),
|
SubStep(context.getString(R.string.patcher_step_load_patches)),
|
||||||
SubStep("Download apk", progress = downloadProgress).takeIf { selectedApp is SelectedApp.Download },
|
SubStep(
|
||||||
|
"Download apk",
|
||||||
|
progress = downloadProgress
|
||||||
|
).takeIf { selectedApp is SelectedApp.Download },
|
||||||
SubStep(context.getString(R.string.patcher_step_unpack)),
|
SubStep(context.getString(R.string.patcher_step_unpack)),
|
||||||
SubStep(context.getString(R.string.patcher_step_integrations))
|
SubStep(context.getString(R.string.patcher_step_integrations))
|
||||||
).toImmutableList()
|
).toImmutableList()
|
||||||
@ -100,7 +113,10 @@ class PatcherProgressManager(context: Context, selectedPatches: List<String>, se
|
|||||||
generatePatchesStep(selectedPatches),
|
generatePatchesStep(selectedPatches),
|
||||||
Step(
|
Step(
|
||||||
R.string.patcher_step_group_saving,
|
R.string.patcher_step_group_saving,
|
||||||
persistentListOf(SubStep(context.getString(R.string.patcher_step_write_patched)))
|
persistentListOf(
|
||||||
|
SubStep(context.getString(R.string.patcher_step_write_patched)),
|
||||||
|
SubStep(context.getString(R.string.patcher_step_sign_apk))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import app.revanced.manager.R
|
|||||||
import app.revanced.manager.data.platform.Filesystem
|
import app.revanced.manager.data.platform.Filesystem
|
||||||
import app.revanced.manager.data.room.apps.installed.InstallType
|
import app.revanced.manager.data.room.apps.installed.InstallType
|
||||||
import app.revanced.manager.domain.installer.RootInstaller
|
import app.revanced.manager.domain.installer.RootInstaller
|
||||||
|
import app.revanced.manager.domain.manager.KeystoreManager
|
||||||
import app.revanced.manager.domain.manager.PreferencesManager
|
import app.revanced.manager.domain.manager.PreferencesManager
|
||||||
import app.revanced.manager.domain.repository.DownloadedAppRepository
|
import app.revanced.manager.domain.repository.DownloadedAppRepository
|
||||||
import app.revanced.manager.domain.repository.InstalledAppRepository
|
import app.revanced.manager.domain.repository.InstalledAppRepository
|
||||||
@ -50,6 +51,7 @@ class PatcherWorker(
|
|||||||
private val patchBundleRepository: PatchBundleRepository by inject()
|
private val patchBundleRepository: PatchBundleRepository by inject()
|
||||||
private val workerRepository: WorkerRepository by inject()
|
private val workerRepository: WorkerRepository by inject()
|
||||||
private val prefs: PreferencesManager by inject()
|
private val prefs: PreferencesManager by inject()
|
||||||
|
private val keystoreManager: KeystoreManager by inject()
|
||||||
private val downloadedAppRepository: DownloadedAppRepository by inject()
|
private val downloadedAppRepository: DownloadedAppRepository by inject()
|
||||||
private val pm: PM by inject()
|
private val pm: PM by inject()
|
||||||
private val fs: Filesystem by inject()
|
private val fs: Filesystem by inject()
|
||||||
@ -159,6 +161,8 @@ class PatcherWorker(
|
|||||||
progressFlow.value = progressManager.getProgress().toImmutableList()
|
progressFlow.value = progressManager.getProgress().toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val patchedApk = fs.tempDir.resolve("patched.apk")
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
|
|
||||||
if (args.input is SelectedApp.Installed) {
|
if (args.input is SelectedApp.Installed) {
|
||||||
@ -219,9 +223,12 @@ class PatcherWorker(
|
|||||||
inputFile,
|
inputFile,
|
||||||
onStepSucceeded = ::updateProgress
|
onStepSucceeded = ::updateProgress
|
||||||
).use { session ->
|
).use { session ->
|
||||||
session.run(File(args.output), patches, integrations)
|
session.run(patchedApk, patches, integrations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keystoreManager.sign(patchedApk, File(args.output))
|
||||||
|
updateProgress() // Signing
|
||||||
|
|
||||||
Log.i(tag, "Patching succeeded".logFmt())
|
Log.i(tag, "Patching succeeded".logFmt())
|
||||||
progressManager.success()
|
progressManager.success()
|
||||||
Result.success()
|
Result.success()
|
||||||
@ -231,6 +238,7 @@ class PatcherWorker(
|
|||||||
Result.failure()
|
Result.failure()
|
||||||
} finally {
|
} finally {
|
||||||
updateProgress(false)
|
updateProgress(false)
|
||||||
|
patchedApk.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,7 +24,6 @@ import app.revanced.manager.data.platform.Filesystem
|
|||||||
import app.revanced.manager.data.room.apps.installed.InstallType
|
import app.revanced.manager.data.room.apps.installed.InstallType
|
||||||
import app.revanced.manager.data.room.apps.installed.InstalledApp
|
import app.revanced.manager.data.room.apps.installed.InstalledApp
|
||||||
import app.revanced.manager.domain.installer.RootInstaller
|
import app.revanced.manager.domain.installer.RootInstaller
|
||||||
import app.revanced.manager.domain.manager.KeystoreManager
|
|
||||||
import app.revanced.manager.domain.repository.InstalledAppRepository
|
import app.revanced.manager.domain.repository.InstalledAppRepository
|
||||||
import app.revanced.manager.domain.worker.WorkerRepository
|
import app.revanced.manager.domain.worker.WorkerRepository
|
||||||
import app.revanced.manager.patcher.worker.PatcherProgressManager
|
import app.revanced.manager.patcher.worker.PatcherProgressManager
|
||||||
@ -57,7 +56,6 @@ import java.util.logging.LogRecord
|
|||||||
class InstallerViewModel(
|
class InstallerViewModel(
|
||||||
private val input: Destination.Installer
|
private val input: Destination.Installer
|
||||||
) : ViewModel(), KoinComponent {
|
) : ViewModel(), KoinComponent {
|
||||||
private val keystoreManager: KeystoreManager by inject()
|
|
||||||
private val app: Application by inject()
|
private val app: Application by inject()
|
||||||
private val fs: Filesystem by inject()
|
private val fs: Filesystem by inject()
|
||||||
private val pm: PM by inject()
|
private val pm: PM by inject()
|
||||||
@ -72,8 +70,6 @@ class InstallerViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val outputFile = tempDir.resolve("output.apk")
|
private val outputFile = tempDir.resolve("output.apk")
|
||||||
private val signedFile = tempDir.resolve("signed.apk")
|
|
||||||
private var hasSigned = false
|
|
||||||
private var inputFile: File? = null
|
private var inputFile: File? = null
|
||||||
|
|
||||||
private var installedApp: InstalledApp? = null
|
private var installedApp: InstalledApp? = null
|
||||||
@ -209,42 +205,22 @@ class InstallerViewModel(
|
|||||||
tempDir.deleteRecursively()
|
tempDir.deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun signApk(): Boolean {
|
|
||||||
if (!hasSigned) {
|
|
||||||
try {
|
|
||||||
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))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun export(uri: Uri?) = viewModelScope.launch {
|
fun export(uri: Uri?) = viewModelScope.launch {
|
||||||
uri?.let {
|
uri?.let {
|
||||||
if (signApk()) {
|
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
app.contentResolver.openOutputStream(it)
|
app.contentResolver.openOutputStream(it)
|
||||||
.use { stream -> Files.copy(signedFile.toPath(), stream) }
|
.use { stream -> Files.copy(outputFile.toPath(), stream) }
|
||||||
}
|
}
|
||||||
app.toast(app.getString(R.string.export_app_success))
|
app.toast(app.getString(R.string.export_app_success))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun install(installType: InstallType) = viewModelScope.launch {
|
fun install(installType: InstallType) = viewModelScope.launch {
|
||||||
isInstalling = true
|
isInstalling = true
|
||||||
try {
|
try {
|
||||||
if (!signApk()) return@launch
|
|
||||||
|
|
||||||
when (installType) {
|
when (installType) {
|
||||||
InstallType.DEFAULT -> {
|
InstallType.DEFAULT -> {
|
||||||
pm.installApp(listOf(signedFile))
|
pm.installApp(listOf(outputFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallType.ROOT -> {
|
InstallType.ROOT -> {
|
||||||
@ -262,7 +238,7 @@ class InstallerViewModel(
|
|||||||
private suspend fun installAsRoot() {
|
private suspend fun installAsRoot() {
|
||||||
try {
|
try {
|
||||||
val label = with(pm) {
|
val label = with(pm) {
|
||||||
getPackageInfo(signedFile)?.label()
|
getPackageInfo(outputFile)?.label()
|
||||||
?: throw Exception("Failed to load application info")
|
?: throw Exception("Failed to load application info")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@
|
|||||||
<string name="patcher_step_group_patching">Patching</string>
|
<string name="patcher_step_group_patching">Patching</string>
|
||||||
<string name="patcher_step_group_saving">Saving</string>
|
<string name="patcher_step_group_saving">Saving</string>
|
||||||
<string name="patcher_step_write_patched">Write patched Apk</string>
|
<string name="patcher_step_write_patched">Write patched Apk</string>
|
||||||
|
<string name="patcher_step_sign_apk">Sign Apk</string>
|
||||||
<string name="patcher_notification_message">Patching in progress…</string>
|
<string name="patcher_notification_message">Patching in progress…</string>
|
||||||
|
|
||||||
<string name="step_completed">completed</string>
|
<string name="step_completed">completed</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user