Skip to content

Commit d403953

Browse files
authored
fix(app): write patched init_boot images to the configured download directory (#217)
* fix(app): write patched init_boot images to the configured download directory The ABK LKM boot/init_boot patch flow (patchAbkLkmBootImage) wrote its patched .img output to app-scoped external storage (Android/data/<pkg>/files/Download/abk-patched), which is invisible to file managers and unlike every other flow that writes to the user's public downloadDirectory (Download/ABK). Thread MainUiState.downloadDirectory through AbkRootPatchScreen into patchAbkLkmBootImage and resolve the output dir via a priority chain: public downloadDirectory/abk-patched -> app-scoped external -> internal filesDir, mirroring DownloadUtils.resolveDownloadsRoot semantics. The output-dir log line is emitted only in image-producing (non-flash) modes. * fix(app): harden init_boot patch output fallback * chore(app): drop redundant patch output comment --------- Co-authored-by: fanziyun <186413865+fanziyun@users.noreply.github.com>
1 parent e081c80 commit d403953

6 files changed

Lines changed: 38 additions & 8 deletions

File tree

app/src/main/java/com/abk/kernel/ui/screens/AbkRootPatchScreen.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ fun AbkRootPatchScreen(
121121
backgroundUri: String?,
122122
backgroundImageEnabled: Boolean,
123123
onBack: () -> Unit,
124-
onBackEnabledChange: (Boolean) -> Unit = {}
124+
onBackEnabledChange: (Boolean) -> Unit = {},
125+
downloadDirectory: String? = null
125126
) {
126127
val context = LocalContext.current
127128
val scope = rememberCoroutineScope()
@@ -377,7 +378,8 @@ fun AbkRootPatchScreen(
377378
allowShell = allowShell,
378379
enableAdb = enableAdb,
379380
localModulePath = modulePath,
380-
onOutput = ::appendLog
381+
onOutput = ::appendLog,
382+
downloadDirectory = downloadDirectory
381383
)
382384
}
383385
finishPatchResult(result)
@@ -409,7 +411,8 @@ fun AbkRootPatchScreen(
409411
allowShell = allowShell,
410412
enableAdb = enableAdb,
411413
localModulePath = modulePath,
412-
onOutput = ::appendLog
414+
onOutput = ::appendLog,
415+
downloadDirectory = downloadDirectory
413416
)
414417
}
415418
finishPatchResult(result)

app/src/main/java/com/abk/kernel/ui/screens/RuntimeScreens.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ fun RuntimeHomeScreen(
260260
runtimeVariant = state.abkRuntimeStatus?.manager?.variant.orEmpty(),
261261
backgroundUri = state.customBackgroundUri,
262262
backgroundImageEnabled = state.backgroundImageEnabled,
263+
downloadDirectory = state.downloadDirectory,
263264
onBack = childPageBack::requestDismiss,
264265
onBackEnabledChange = { managerPatchBackEnabled = it }
265266
)

app/src/main/java/com/abk/kernel/utils/RootUtils.kt

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.topjohnwu.superuser.CallbackList
2121
import com.topjohnwu.superuser.Shell
2222
import org.json.JSONObject
2323
import java.io.File
24+
import java.io.IOException
2425
import java.util.Collections
2526
import java.util.Properties
2627
import java.security.MessageDigest
@@ -476,7 +477,8 @@ object RootUtils {
476477
allowShell: Boolean = false,
477478
enableAdb: Boolean = false,
478479
localModulePath: String? = null,
479-
onOutput: ((String) -> Unit)? = null
480+
onOutput: ((String) -> Unit)? = null,
481+
downloadDirectory: String? = null
480482
): BootPatchResult {
481483
val sourceBoot = bootImagePath
482484
?.takeIf { it.isNotBlank() }
@@ -511,10 +513,19 @@ object RootUtils {
511513
stageBundledAbkLkmAsset(context, workDir, checkNotNull(asset))
512514
}
513515

514-
val outputDir = File(
515-
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) ?: context.filesDir,
516-
"abk-patched"
517-
).apply { mkdirs() }
516+
val appScopedOutputCandidates = listOfNotNull(
517+
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
518+
?.let { File(it, "abk-patched") },
519+
File(context.filesDir, "abk-patched")
520+
)
521+
val outputDir = (if (flash) null else resolvePatchOutputDir(downloadDirectory))
522+
?: appScopedOutputCandidates.firstNotNullOfOrNull(::prepareWritableDirectory)
523+
?: throw IOException(
524+
tr(R.string.download_directory_create_failed, context.filesDir.absolutePath)
525+
)
526+
if (!flash) {
527+
onOutput?.invoke(tr(R.string.ru_log_output_dir, outputDir.absolutePath))
528+
}
518529
val moduleName = (asset?.let { "${it.variantId}-${it.kmi}" } ?: moduleFile.nameWithoutExtension)
519530
.replace(Regex("""[^A-Za-z0-9._-]"""), "_")
520531
val outputName = "abk-${moduleName}-patched-${System.currentTimeMillis()}.img"
@@ -2266,6 +2277,18 @@ object RootUtils {
22662277
return target
22672278
}
22682279

2280+
internal fun resolvePatchOutputDir(downloadDirectory: String?): File? {
2281+
val root = prepareWritableDirectory(
2282+
File(DownloadDirectoryUtils.normalizeDirectoryPath(downloadDirectory))
2283+
) ?: return null
2284+
return prepareWritableDirectory(File(root, "abk-patched"))
2285+
}
2286+
2287+
private fun prepareWritableDirectory(directory: File): File? {
2288+
if (!directory.exists() && !directory.mkdirs()) return null
2289+
return directory.takeIf { it.isDirectory && it.canWrite() }
2290+
}
2291+
22692292
private fun buildBootPatchArgs(
22702293
context: Context,
22712294
bootImage: File?,

app/src/main/res/values-en/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,7 @@
12241224
<string name="ru_lkm_module_not_bundled">No bundled LKM module for %1$s / %2$s</string>
12251225
<string name="ru_log_using_bundled_lkm">[ABK] Using APK-bundled LKM: %1$s · %2$s</string>
12261226
<string name="ru_log_using_local_lkm">[ABK] Using local LKM: %1$s</string>
1227+
<string name="ru_log_output_dir">[ABK] Output directory: %1$s</string>
12271228
<string name="ru_log_no_root_shell_local_patch">[ABK] Root shell unavailable; falling back to APK-bundled SukiSU-Ultra ksud to patch the local boot image only</string>
12281229
<string name="ru_no_embedded_ksud">No runnable APK-bundled SukiSU-Ultra ksud found; without root you can only generate a patched image after selecting boot.img.</string>
12291230
<string name="ru_install_requires_root">This installation method requires root permission.</string>

app/src/main/res/values-ru/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,7 @@
12231223
<string name="ru_lkm_module_not_bundled">Нет встроенного LKM-модуля для %1$s / %2$s</string>
12241224
<string name="ru_log_using_bundled_lkm">[ABK] Используется встроенный в APK LKM: %1$s · %2$s</string>
12251225
<string name="ru_log_using_local_lkm">[ABK] Используется локальный LKM: %1$s</string>
1226+
<string name="ru_log_output_dir">[ABK] Каталог вывода: %1$s</string>
12261227
<string name="ru_log_no_root_shell_local_patch">[ABK] Root shell недоступен — переходим на встроенный в APK SukiSU-Ultra ksud для патча только локального образа boot</string>
12271228
<string name="ru_no_embedded_ksud">Исполняемый встроенный в APK SukiSU-Ultra ksud не найден; без root можно только сгенерировать пропатченный образ после выбора boot.img.</string>
12281229
<string name="ru_install_requires_root">Этот способ установки требует прав root.</string>

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,7 @@
12961296
<string name="ru_lkm_module_not_bundled">未内置 %1$s / %2$s 的 LKM 模块</string>
12971297
<string name="ru_log_using_bundled_lkm">[ABK] 使用 APK 内置 LKM: %1$s · %2$s</string>
12981298
<string name="ru_log_using_local_lkm">[ABK] 使用本地 LKM: %1$s</string>
1299+
<string name="ru_log_output_dir">[ABK] 输出目录: %1$s</string>
12991300
<string name="ru_log_no_root_shell_local_patch">[ABK] Root shell 不可用,改用 APK 内置 SukiSU-Ultra ksud 仅修补本地 boot 镜像</string>
13001301
<string name="ru_no_embedded_ksud">未找到可执行的 APK 内置 SukiSU-Ultra ksud;无 Root 时只能在选择 boot.img 后生成 patched 镜像。</string>
13011302
<string name="ru_install_requires_root">该安装方式需要 Root 权限。</string>

0 commit comments

Comments
 (0)