-Optimize file permission requests, simplify backup and restore logic, and directly process user-selected files
- This will fix an issue where some devices were unable to back up their app lists
This commit is contained in:
@@ -3,10 +3,9 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
|
||||
<application
|
||||
android:name=".KernelSUApplication"
|
||||
@@ -19,6 +18,7 @@
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.KernelSU"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
tools:targetApi="34">
|
||||
<activity
|
||||
android:name=".ui.MainActivity"
|
||||
|
||||
@@ -18,7 +18,6 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import shirkneko.zako.sukisu.R
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.text.SimpleDateFormat
|
||||
@@ -45,30 +44,25 @@ object ModuleModify {
|
||||
try {
|
||||
val busyboxPath = "/data/adb/ksu/bin/busybox"
|
||||
val moduleDir = "/data/adb/modules"
|
||||
val tempFile = File(context.cacheDir, "backup_${System.currentTimeMillis()}.tar.gz")
|
||||
val tempPath = tempFile.absolutePath
|
||||
|
||||
// 直接将tar输出重定向到用户选择的文件
|
||||
val command = """
|
||||
cd "$moduleDir" &&
|
||||
$busyboxPath tar -czvf "$tempPath" ./*
|
||||
$busyboxPath tar -cz ./* > /proc/self/fd/1
|
||||
""".trimIndent()
|
||||
|
||||
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", command))
|
||||
process.waitFor()
|
||||
|
||||
// 直接将tar输出写入到用户选择的文件
|
||||
context.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
process.inputStream.copyTo(output)
|
||||
}
|
||||
|
||||
val error = BufferedReader(InputStreamReader(process.errorStream)).readText()
|
||||
if (process.exitValue() != 0) {
|
||||
throw IOException(context.getString(R.string.command_execution_failed, error))
|
||||
}
|
||||
|
||||
context.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
tempFile.inputStream().use { input ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
|
||||
tempFile.delete()
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
snackBarHost.showSnackbar(
|
||||
context.getString(R.string.backup_success),
|
||||
@@ -96,23 +90,15 @@ object ModuleModify {
|
||||
try {
|
||||
val busyboxPath = "/data/adb/ksu/bin/busybox"
|
||||
val moduleDir = "/data/adb/modules"
|
||||
val tempFile = File(context.cacheDir, "temp_restore.tar.gz").apply {
|
||||
if (exists()) delete()
|
||||
}
|
||||
|
||||
// 直接从用户选择的文件读取并解压
|
||||
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", "$busyboxPath tar -xz -C $moduleDir"))
|
||||
|
||||
context.contentResolver.openInputStream(uri)?.use { input ->
|
||||
tempFile.outputStream().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
input.copyTo(process.outputStream)
|
||||
}
|
||||
process.outputStream.close()
|
||||
|
||||
val command = """
|
||||
cd "$moduleDir" &&
|
||||
rm -rf * &&
|
||||
$busyboxPath tar -xzvf "${tempFile.absolutePath}"
|
||||
""".trimIndent()
|
||||
|
||||
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", command))
|
||||
process.waitFor()
|
||||
|
||||
val error = BufferedReader(InputStreamReader(process.errorStream)).readText()
|
||||
@@ -120,8 +106,6 @@ object ModuleModify {
|
||||
throw IOException(context.getString(R.string.command_execution_failed, error))
|
||||
}
|
||||
|
||||
tempFile.delete()
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
val snackbarResult = snackBarHost.showSnackbar(
|
||||
message = context.getString(R.string.restore_success),
|
||||
@@ -166,25 +150,19 @@ object ModuleModify {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val allowlistPath = "/data/adb/ksu/.allowlist"
|
||||
val tempFile = File(context.cacheDir, "allowlist_backup_${System.currentTimeMillis()}")
|
||||
|
||||
val command = "cp $allowlistPath ${tempFile.absolutePath}"
|
||||
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", command))
|
||||
process.waitFor()
|
||||
// 直接复制文件到用户选择的位置
|
||||
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", "cat $allowlistPath"))
|
||||
|
||||
context.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
process.inputStream.copyTo(output)
|
||||
}
|
||||
|
||||
val error = BufferedReader(InputStreamReader(process.errorStream)).readText()
|
||||
if (process.exitValue() != 0) {
|
||||
throw IOException(context.getString(R.string.command_execution_failed, error))
|
||||
}
|
||||
|
||||
context.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
tempFile.inputStream().use { input ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
|
||||
tempFile.delete()
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
snackBarHost.showSnackbar(
|
||||
context.getString(R.string.allowlist_backup_success),
|
||||
@@ -211,18 +189,15 @@ object ModuleModify {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val allowlistPath = "/data/adb/ksu/.allowlist"
|
||||
val tempFile = File(context.cacheDir, "allowlist_restore_temp").apply {
|
||||
if (exists()) delete()
|
||||
}
|
||||
|
||||
// 直接从用户选择的文件读取并写入到目标位置
|
||||
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", "cat > $allowlistPath"))
|
||||
|
||||
context.contentResolver.openInputStream(uri)?.use { input ->
|
||||
tempFile.outputStream().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
input.copyTo(process.outputStream)
|
||||
}
|
||||
process.outputStream.close()
|
||||
|
||||
val command = "cp ${tempFile.absolutePath} $allowlistPath"
|
||||
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", command))
|
||||
process.waitFor()
|
||||
|
||||
val error = BufferedReader(InputStreamReader(process.errorStream)).readText()
|
||||
@@ -230,8 +205,6 @@ object ModuleModify {
|
||||
throw IOException(context.getString(R.string.command_execution_failed, error))
|
||||
}
|
||||
|
||||
tempFile.delete()
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
snackBarHost.showSnackbar(
|
||||
context.getString(R.string.allowlist_restore_success),
|
||||
@@ -350,4 +323,8 @@ object ModuleModify {
|
||||
type = "application/octet-stream"
|
||||
}
|
||||
}
|
||||
|
||||
private fun reboot() {
|
||||
Runtime.getRuntime().exec(arrayOf("su", "-c", "reboot"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user