From 187bd4c89d2b27904bccf8ff3b882cf3b04c5019 Mon Sep 17 00:00:00 2001 From: Nullptr <52071314+Dr-TSNG@users.noreply.github.com> Date: Sun, 20 Feb 2022 15:06:53 +0800 Subject: [PATCH] Fix saving content (2/2) --- manager/build.gradle.kts | 11 ++++---- .../main/java/org/lsposed/lspatch/Patcher.kt | 13 +++++++-- .../lsposed/lspatch/ui/page/NewPatchPage.kt | 27 +++++++++++++++++++ manager/src/main/res/values/strings.xml | 2 ++ 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/manager/build.gradle.kts b/manager/build.gradle.kts index 4ac69c2..586087d 100644 --- a/manager/build.gradle.kts +++ b/manager/build.gradle.kts @@ -82,17 +82,18 @@ dependencies { implementation(projects.patch) implementation("androidx.core:core-ktx:1.7.0") - implementation("androidx.activity:activity-compose:1.5.0-alpha01") - implementation("androidx.compose.material:material-icons-extended:1.0.5") - implementation("androidx.compose.material3:material3:1.0.0-alpha04") + implementation("androidx.activity:activity-compose:1.5.0-alpha02") + implementation("androidx.compose.material:material-icons-extended:1.1.0") + implementation("androidx.compose.material3:material3:1.0.0-alpha05") implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") implementation("androidx.compose.ui:ui:$composeVersion") implementation("androidx.compose.ui:ui-tooling:$composeVersion") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha01") - implementation("androidx.navigation:navigation-compose:2.5.0-alpha01") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha02") + implementation("androidx.navigation:navigation-compose:2.5.0-alpha02") implementation("androidx.preference:preference:1.2.0") implementation("com.google.accompanist:accompanist-drawablepainter:0.24.2-alpha") implementation("com.google.accompanist:accompanist-navigation-animation:0.24.2-alpha") + implementation("com.google.accompanist:accompanist-permissions:0.24.2-alpha") implementation("com.google.accompanist:accompanist-swiperefresh:0.24.2-alpha") implementation("com.google.android.material:material:1.5.0") } diff --git a/manager/src/main/java/org/lsposed/lspatch/Patcher.kt b/manager/src/main/java/org/lsposed/lspatch/Patcher.kt index 8afb1a3..eaf3897 100644 --- a/manager/src/main/java/org/lsposed/lspatch/Patcher.kt +++ b/manager/src/main/java/org/lsposed/lspatch/Patcher.kt @@ -52,14 +52,23 @@ object Patcher { suspend fun patch(context: Context, logger: Logger, options: Options) { withContext(Dispatchers.IO) { val download = "${Environment.DIRECTORY_DOWNLOADS}/LSPatch" + val externalStorageDir = Environment.getExternalStoragePublicDirectory(download) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) externalStorageDir.mkdirs() options.outputPath = Files.createTempDirectory("patch").absolutePathString() + LSPatch(logger, *options.toStringArray()).doCommandLine() + File(options.outputPath) .walk() .filter { it.isFile } .forEach { - //FIXME: Android 9 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + it.inputStream().use { input -> + externalStorageDir.resolve(it.name).outputStream().use { output -> + input.copyTo(output) + } + } + } else { val contentDetails = ContentValues().apply { put(MediaStore.Downloads.DISPLAY_NAME, it.name) put(MediaStore.Downloads.RELATIVE_PATH, download) diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchPage.kt b/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchPage.kt index 3716f5e..ebdb44e 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchPage.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchPage.kt @@ -1,5 +1,6 @@ package org.lsposed.lspatch.ui.page +import android.os.Build import android.util.Log import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.Spring @@ -30,6 +31,9 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.viewModel +import com.google.accompanist.permissions.ExperimentalPermissionsApi +import com.google.accompanist.permissions.PermissionStatus +import com.google.accompanist.permissions.rememberPermissionState import org.lsposed.lspatch.Patcher import org.lsposed.lspatch.R import org.lsposed.lspatch.TAG @@ -66,6 +70,7 @@ fun NewPatchFab() { } } +@OptIn(ExperimentalPermissionsApi::class) @Composable fun NewPatchPage() { val viewModel = viewModel() @@ -73,6 +78,28 @@ fun NewPatchPage() { val patchApp by navController.currentBackStackEntry!!.observeState("appInfo") if (viewModel.patchState == PatchState.SELECTING && patchApp != null) viewModel.patchState = PatchState.CONFIGURING + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + val filePermissionState = rememberPermissionState(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) + if (filePermissionState.status is PermissionStatus.Denied) { + AlertDialog( + onDismissRequest = {}, + confirmButton = { + TextButton(onClick = { filePermissionState.launchPermissionRequest() }) { + Text(stringResource(android.R.string.ok)) + } + }, + dismissButton = { + TextButton(onClick = { navController.popBackStack() }) { + Text(stringResource(android.R.string.cancel)) + } + }, + title = { Text(stringResource(R.string.patch_permission_title)) }, + text = { Text(stringResource(R.string.patch_permission_text)) } + ) + return + } + } + Log.d(TAG, "NewPatchPage: ${viewModel.patchState}") when (viewModel.patchState) { PatchState.SELECTING -> navController.navigate(PageList.SelectApps.name + "/false") diff --git a/manager/src/main/res/values/strings.xml b/manager/src/main/res/values/strings.xml index 2e07c69..e72c798 100644 --- a/manager/src/main/res/values/strings.xml +++ b/manager/src/main/res/values/strings.xml @@ -10,6 +10,8 @@ New Patch + Permission + Please grant Write External Storage permission to allow saving patched apks to Download directory Patch Mode Local Patch an app without modules embedded.\nThe patched app need the manager running in background, and Xposed scope can be changed dynamically without re-patch.\nLocal patched apps can only run on the local device.