feat: abort patching process at any time (#1072)

This commit is contained in:
aAbed 2023-08-04 03:25:08 +05:45 committed by GitHub
parent fe75b75ddc
commit 374eb3d06d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 6 deletions

View File

@ -27,6 +27,8 @@ private const val INSTALLER_CHANNEL = "app.revanced.manager.flutter/installer"
class MainActivity : FlutterActivity() { class MainActivity : FlutterActivity() {
private val handler = Handler(Looper.getMainLooper()) private val handler = Handler(Looper.getMainLooper())
private lateinit var installerChannel: MethodChannel private lateinit var installerChannel: MethodChannel
private var cancel: Boolean = false
private var stopResult: MethodChannel.Result? = null
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine) super.configureFlutterEngine(flutterEngine)
@ -57,6 +59,7 @@ class MainActivity : FlutterActivity() {
keyStoreFilePath != null && keyStoreFilePath != null &&
keystorePassword != null keystorePassword != null
) { ) {
cancel = false
runPatcher( runPatcher(
result, result,
patchBundleFilePath, patchBundleFilePath,
@ -74,6 +77,10 @@ class MainActivity : FlutterActivity() {
result.notImplemented() result.notImplemented()
} }
} }
"stopPatcher" -> {
cancel = true
stopResult = result
}
else -> result.notImplemented() else -> result.notImplemented()
} }
} }
@ -111,6 +118,12 @@ class MainActivity : FlutterActivity() {
) )
) )
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
originalFile.copyTo(inputFile, true) originalFile.copyTo(inputFile, true)
handler.post { handler.post {
@ -123,6 +136,12 @@ class MainActivity : FlutterActivity() {
) )
) )
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
val patcher = val patcher =
Patcher( Patcher(
PatcherOptions( PatcherOptions(
@ -134,6 +153,11 @@ class MainActivity : FlutterActivity() {
) )
) )
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
handler.post { handler.post {
installerChannel.invokeMethod( installerChannel.invokeMethod(
"update", "update",
@ -150,8 +174,19 @@ class MainActivity : FlutterActivity() {
) )
) )
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
patcher.addIntegrations(listOf(integrations)) {} patcher.addIntegrations(listOf(integrations)) {}
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
handler.post { handler.post {
installerChannel.invokeMethod( installerChannel.invokeMethod(
"update", "update",
@ -163,6 +198,11 @@ class MainActivity : FlutterActivity() {
) )
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
val patches = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) { val patches = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
PatchBundle.Dex( PatchBundle.Dex(
patchBundleFilePath, patchBundleFilePath,
@ -179,6 +219,12 @@ class MainActivity : FlutterActivity() {
} else { } else {
TODO("VERSION.SDK_INT < CUPCAKE") TODO("VERSION.SDK_INT < CUPCAKE")
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
patcher.addPatches(patches) patcher.addPatches(patches)
patcher.executePatches().forEach { (patch, res) -> patcher.executePatches().forEach { (patch, res) ->
if (res.isSuccess) { if (res.isSuccess) {
@ -193,15 +239,24 @@ class MainActivity : FlutterActivity() {
) )
) )
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
return@forEach return@forEach
} }
val msg = "Failed to apply $patch: " + "${res.exceptionOrNull()!!.message ?: res.exceptionOrNull()!!.cause!!::class.simpleName}" val msg =
"Failed to apply $patch: " + "${res.exceptionOrNull()!!.message ?: res.exceptionOrNull()!!.cause!!::class.simpleName}"
handler.post { handler.post {
installerChannel.invokeMethod( installerChannel.invokeMethod(
"update", "update",
mapOf("progress" to 0.5, "header" to "", "log" to msg) mapOf("progress" to 0.5, "header" to "", "log" to msg)
) )
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
} }
handler.post { handler.post {
@ -214,9 +269,17 @@ class MainActivity : FlutterActivity() {
) )
) )
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
val res = patcher.save() val res = patcher.save()
ZipFile(patchedFile).use { file -> ZipFile(patchedFile).use { file ->
res.dexFiles.forEach { res.dexFiles.forEach {
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
file.addEntryCompressData( file.addEntryCompressData(
ZipEntry.createWithName(it.name), ZipEntry.createWithName(it.name),
it.stream.readBytes() it.stream.readBytes()
@ -233,6 +296,10 @@ class MainActivity : FlutterActivity() {
ZipAligner::getEntryAlignment ZipAligner::getEntryAlignment
) )
} }
if(cancel) {
handler.post { stopResult!!.success(null) }
return@Thread
}
handler.post { handler.post {
installerChannel.invokeMethod( installerChannel.invokeMethod(
"update", "update",
@ -244,10 +311,12 @@ class MainActivity : FlutterActivity() {
) )
} }
// Signer("ReVanced", "s3cur3p@ssw0rd").signApk(patchedFile, outFile, keyStoreFile)
try { try {
Signer("ReVanced", keystorePassword).signApk(patchedFile, outFile, keyStoreFile) Signer("ReVanced", keystorePassword).signApk(
patchedFile,
outFile,
keyStoreFile
)
} catch (e: Exception) { } catch (e: Exception) {
//log to console //log to console
print("Error signing apk: ${e.message}") print("Error signing apk: ${e.message}")

View File

@ -135,6 +135,7 @@
"widgetTitle": "Installer", "widgetTitle": "Installer",
"installButton": "Install", "installButton": "Install",
"installRootButton": "Install as Root", "installRootButton": "Install as Root",
"pressBackAgain": "Press back again to cancel",
"openButton": "Open", "openButton": "Open",
"shareButton": "Share file", "shareButton": "Share file",

View File

@ -202,6 +202,16 @@ class PatcherAPI {
} }
} }
Future<void> stopPatcher() async {
try {
await patcherChannel.invokeMethod('stopPatcher');
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
}
}
Future<bool> installPatchedFile(PatchedApplication patchedApp) async { Future<bool> installPatchedFile(PatchedApplication patchedApp) async {
if (_outFile != null) { if (_outFile != null) {
try { try {

View File

@ -36,6 +36,8 @@ class InstallerViewModel extends BaseViewModel {
bool isPatching = true; bool isPatching = true;
bool isInstalled = false; bool isInstalled = false;
bool hasErrors = false; bool hasErrors = false;
bool isCanceled = false;
bool cancel = false;
Future<void> initialize(BuildContext context) async { Future<void> initialize(BuildContext context) async {
isRooted = await _rootAPI.isRooted(); isRooted = await _rootAPI.isRooted();
@ -162,6 +164,19 @@ class InstallerViewModel extends BaseViewModel {
} }
} }
Future<void> stopPatcher() async {
try {
isCanceled = true;
update(0.5, 'Aborting...', 'Canceling patching process');
await _patcherAPI.stopPatcher();
update(-100.0, 'Aborted...', 'Press back to exit');
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
}
}
Future<void> installResult(BuildContext context, bool installAsRoot) async { Future<void> installResult(BuildContext context, bool installAsRoot) async {
try { try {
_app.isRooted = installAsRoot; _app.isRooted = installAsRoot;
@ -280,10 +295,21 @@ class InstallerViewModel extends BaseViewModel {
Future<bool> onWillPop(BuildContext context) async { Future<bool> onWillPop(BuildContext context) async {
if (isPatching) { if (isPatching) {
_toast.showBottom('installerView.noExit'); if (!cancel) {
cancel = true;
_toast.showBottom('installerView.pressBackAgain');
} else if (!isCanceled) {
await stopPatcher();
} else {
_toast.showBottom('installerView.noExit');
}
return false; return false;
} }
cleanPatcher(); if (!cancel) {
cleanPatcher();
} else {
_patcherAPI.cleanPatcher();
}
Navigator.of(context).pop(); Navigator.of(context).pop();
return true; return true;
} }