Fix saving content (2/2)

This commit is contained in:
Nullptr 2022-02-20 15:06:53 +08:00
parent 0bd40ca4dd
commit 187bd4c89d
4 changed files with 46 additions and 7 deletions

View File

@ -82,17 +82,18 @@ dependencies {
implementation(projects.patch) implementation(projects.patch)
implementation("androidx.core:core-ktx:1.7.0") implementation("androidx.core:core-ktx:1.7.0")
implementation("androidx.activity:activity-compose:1.5.0-alpha01") implementation("androidx.activity:activity-compose:1.5.0-alpha02")
implementation("androidx.compose.material:material-icons-extended:1.0.5") implementation("androidx.compose.material:material-icons-extended:1.1.0")
implementation("androidx.compose.material3:material3:1.0.0-alpha04") implementation("androidx.compose.material3:material3:1.0.0-alpha05")
implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") implementation("androidx.compose.runtime:runtime-livedata:$composeVersion")
implementation("androidx.compose.ui:ui:$composeVersion") implementation("androidx.compose.ui:ui:$composeVersion")
implementation("androidx.compose.ui:ui-tooling:$composeVersion") implementation("androidx.compose.ui:ui-tooling:$composeVersion")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha01") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha02")
implementation("androidx.navigation:navigation-compose:2.5.0-alpha01") implementation("androidx.navigation:navigation-compose:2.5.0-alpha02")
implementation("androidx.preference:preference:1.2.0") implementation("androidx.preference:preference:1.2.0")
implementation("com.google.accompanist:accompanist-drawablepainter:0.24.2-alpha") 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-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.accompanist:accompanist-swiperefresh:0.24.2-alpha")
implementation("com.google.android.material:material:1.5.0") implementation("com.google.android.material:material:1.5.0")
} }

View File

@ -52,14 +52,23 @@ object Patcher {
suspend fun patch(context: Context, logger: Logger, options: Options) { suspend fun patch(context: Context, logger: Logger, options: Options) {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val download = "${Environment.DIRECTORY_DOWNLOADS}/LSPatch" 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() options.outputPath = Files.createTempDirectory("patch").absolutePathString()
LSPatch(logger, *options.toStringArray()).doCommandLine() LSPatch(logger, *options.toStringArray()).doCommandLine()
File(options.outputPath) File(options.outputPath)
.walk() .walk()
.filter { it.isFile } .filter { it.isFile }
.forEach { .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 { val contentDetails = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, it.name) put(MediaStore.Downloads.DISPLAY_NAME, it.name)
put(MediaStore.Downloads.RELATIVE_PATH, download) put(MediaStore.Downloads.RELATIVE_PATH, download)

View File

@ -1,5 +1,6 @@
package org.lsposed.lspatch.ui.page package org.lsposed.lspatch.ui.page
import android.os.Build
import android.util.Log import android.util.Log
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring 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.compose.ui.unit.dp
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.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.Patcher
import org.lsposed.lspatch.R import org.lsposed.lspatch.R
import org.lsposed.lspatch.TAG import org.lsposed.lspatch.TAG
@ -66,6 +70,7 @@ fun NewPatchFab() {
} }
} }
@OptIn(ExperimentalPermissionsApi::class)
@Composable @Composable
fun NewPatchPage() { fun NewPatchPage() {
val viewModel = viewModel<NewPatchPageViewModel>() val viewModel = viewModel<NewPatchPageViewModel>()
@ -73,6 +78,28 @@ fun NewPatchPage() {
val patchApp by navController.currentBackStackEntry!!.observeState<AppInfo>("appInfo") val patchApp by navController.currentBackStackEntry!!.observeState<AppInfo>("appInfo")
if (viewModel.patchState == PatchState.SELECTING && patchApp != null) viewModel.patchState = PatchState.CONFIGURING 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}") Log.d(TAG, "NewPatchPage: ${viewModel.patchState}")
when (viewModel.patchState) { when (viewModel.patchState) {
PatchState.SELECTING -> navController.navigate(PageList.SelectApps.name + "/false") PatchState.SELECTING -> navController.navigate(PageList.SelectApps.name + "/false")

View File

@ -10,6 +10,8 @@
<!-- New Patch Page --> <!-- New Patch Page -->
<string name="page_new_patch">New Patch</string> <string name="page_new_patch">New Patch</string>
<string name="patch_permission_title">Permission</string>
<string name="patch_permission_text">Please grant Write External Storage permission to allow saving patched apks to Download directory</string>
<string name="patch_mode">Patch Mode</string> <string name="patch_mode">Patch Mode</string>
<string name="patch_local">Local</string> <string name="patch_local">Local</string>
<string name="patch_local_desc">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.</string> <string name="patch_local_desc">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.</string>