Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

Commit

Permalink
feat: select module(s) from storage (#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonKhew96 authored Oct 12, 2023
1 parent b0fbc73 commit 8462043
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ fun NewPatchScreen(
) {
val viewModel = viewModel<NewPatchViewModel>()
val snackbarHost = LocalSnackbarHost.current
val errorUnknown = stringResource(R.string.error_unknown)
val storageLauncher = rememberLauncherForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { apks ->
if (apks.isEmpty()) {
navigator.navigateUp()
Expand All @@ -76,15 +77,40 @@ fun NewPatchScreen(
runBlocking {
LSPPackageManager.getAppInfoFromApks(apks)
.onSuccess {
viewModel.dispatch(ViewAction.ConfigurePatch(it))
viewModel.dispatch(ViewAction.ConfigurePatch(it.first()))
}
.onFailure {
lspApp.globalScope.launch { snackbarHost.showSnackbar(it.message ?: "Unknown error") }
lspApp.globalScope.launch { snackbarHost.showSnackbar(it.message ?: errorUnknown) }
navigator.navigateUp()
}
}
}

var showSelectModuleDialog by remember { mutableStateOf(false) }
val noXposedModules = stringResource(R.string.patch_no_xposed_module)
val storageModuleLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { apks ->
if (apks.isEmpty()) {
return@rememberLauncherForActivityResult
}
runBlocking {
LSPPackageManager.getAppInfoFromApks(apks).onSuccess { it ->
viewModel.embeddedModules = it.filter { it.isXposedModule }.ifEmpty {
lspApp.globalScope.launch {
snackbarHost.showSnackbar(noXposedModules)
}
return@onSuccess
}
}.onFailure {
lspApp.globalScope.launch {
snackbarHost.showSnackbar(
it.message ?: errorUnknown
)
}
}
}
}

Log.d(TAG, "PatchState: ${viewModel.patchState}")
when (viewModel.patchState) {
PatchState.INIT -> {
Expand Down Expand Up @@ -128,7 +154,7 @@ fun NewPatchScreen(
) { innerPadding ->
if (viewModel.patchState == PatchState.CONFIGURING) {
PatchOptionsBody(Modifier.padding(innerPadding)) {
navigator.navigate(SelectAppsScreenDestination(true, viewModel.embeddedModules.mapTo(ArrayList()) { it.app.packageName }))
showSelectModuleDialog = true
}
resultRecipient.onNavResult {
if (it is NavResult.Value) {
Expand All @@ -140,6 +166,53 @@ fun NewPatchScreen(
DoPatchBody(Modifier.padding(innerPadding), navigator)
}
}

if (showSelectModuleDialog) {
AlertDialog(onDismissRequest = { showSelectModuleDialog = false },
confirmButton = {},
dismissButton = {
TextButton(content = { Text(stringResource(android.R.string.cancel)) },
onClick = { showSelectModuleDialog = false })
},
title = {
Text(
modifier = Modifier.fillMaxWidth(),
text = stringResource(R.string.patch_embed_modules),
textAlign = TextAlign.Center
)
},
text = {
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
TextButton(modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.secondary),
onClick = {
storageModuleLauncher.launch(arrayOf("application/vnd.android.package-archive"))
showSelectModuleDialog = false
}) {
Text(
modifier = Modifier.padding(vertical = 8.dp),
text = stringResource(R.string.patch_from_storage),
style = MaterialTheme.typography.bodyLarge
)
}
TextButton(modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.secondary),
onClick = {
navigator.navigate(
SelectAppsScreenDestination(true,
viewModel.embeddedModules.mapTo(ArrayList()) { it.app.packageName })
)
showSelectModuleDialog = false
}) {
Text(
modifier = Modifier.padding(vertical = 8.dp),
text = stringResource(R.string.patch_from_applist),
style = MaterialTheme.typography.bodyLarge
)
}
}
})
}
}
}
}
Expand Down
31 changes: 18 additions & 13 deletions manager/src/main/java/org/lsposed/lspatch/util/LSPPackageManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,12 @@ object LSPPackageManager {
return Pair(status, message)
}

suspend fun getAppInfoFromApks(apks: List<Uri>): Result<AppInfo> {
suspend fun getAppInfoFromApks(apks: List<Uri>): Result<List<AppInfo>> {
return withContext(Dispatchers.IO) {
runCatching {
var primary: ApplicationInfo? = null
val splits = apks.mapNotNull { uri ->
val splits = mutableListOf<String>()
val appInfos = apks.mapNotNull { uri ->
val src = DocumentFile.fromSingleUri(lspApp, uri)
?: throw IOException("DocumentFile is null")
val dst = lspApp.tmpApkDir.resolve(src.name!!)
Expand All @@ -167,21 +168,25 @@ object LSPPackageManager {
input.copyTo(output)
}
}

val appInfo = lspApp.packageManager.getPackageArchiveInfo(
dst.absolutePath, PackageManager.GET_META_DATA
)?.applicationInfo
appInfo?.sourceDir = dst.absolutePath
if (appInfo == null) {
splits.add(dst.absolutePath)
return@mapNotNull null
}
if (primary == null) {
primary = lspApp.packageManager.getPackageArchiveInfo(dst.absolutePath, 0)?.applicationInfo
primary?.let {
it.sourceDir = dst.absolutePath
return@mapNotNull null
}
primary = appInfo
}
dst.absolutePath
val label = lspApp.packageManager.getApplicationLabel(appInfo).toString()
AppInfo(appInfo, label)
}

// TODO: Check selected apks are from the same app
if (primary == null) throw IllegalArgumentException("No primary apk")
val label = lspApp.packageManager.getApplicationLabel(primary!!).toString()
if (splits.isNotEmpty()) primary!!.splitSourceDirs = splits.toTypedArray()
AppInfo(primary!!, label)
primary?.splitSourceDirs = splits.toTypedArray()
if (appInfos.isEmpty()) throw IOException("No apks")
appInfos
}.recoverCatching { t ->
cleanTmpApkDir()
Log.e(TAG, "Failed to load apks", t)
Expand Down
2 changes: 2 additions & 0 deletions manager/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<string name="screen_repo">Repo</string>
<string name="screen_logs">Logs</string>
<string name="off">Off</string>
<string name="error_unknown">Unknown error</string>

<!-- Home Screen -->
<string name="home_shizuku_warning">Some functions unavailable</string>
Expand Down Expand Up @@ -68,6 +69,7 @@
<string name="patch_uninstall_text">Due to different signatures, you need to uninstall the original app before installing the patched one.\nMake sure you have backed up personal data.</string>
<string name="patch_install_successfully">Install successfully</string>
<string name="patch_install_failed">Install failed</string>
<string name="patch_no_xposed_module">No Xposed module(s) were found</string>

<!-- Select Apps Screen -->
<string name="screen_select_apps">Select Apps</string>
Expand Down

0 comments on commit 8462043

Please sign in to comment.