如何获取AndroidP7zip库输出流以实现解压进度监听?
捕获AndroidP7zip的解压进度(Kotlin实现)
你提到的P7ZipApi.executeCommand应该是封装了基础的进程调用,但没暴露标准输出的捕获能力。要获取-bsp2输出的进度,得手动通过ProcessBuilder创建进程,然后读取其标准输出流。
核心实现思路
- 用
ProcessBuilder构建7z命令,替代封装好的executeCommand - 开启独立线程(或协程)读取进程的标准输出,避免阻塞主线程
- 解析输出中的百分比数值,用于更新UI或记录进度
完整Kotlin代码示例
import android.os.Looper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.BufferedReader import java.io.InputStreamReader fun extractWithProgress( sourcePath: String, outputDir: String, password: String, onProgressUpdate: (Int) -> Unit, onExtractionComplete: (Boolean) -> Unit ) { // 构建7z命令,-bsp2指定输出进度到stdout val command = listOf( "7z", "x", sourcePath, "-o${outputDir}", "-p${password}", "-bsp2" ) GlobalScope.launch(Dispatchers.IO) { var process: Process? = null try { process = ProcessBuilder(command).start() // 读取标准输出流 BufferedReader(InputStreamReader(process.inputStream)).use { reader -> var line: String? while (reader.readLine().also { line = it } != null) { line?.trim()?.let { progressLine -> // 提取百分比数字(格式如"1%"、"100%") val progress = progressLine.removeSuffix("%").toIntOrNull() progress?.let { // 切换到主线程更新UI withContext(Dispatchers.Main) { onProgressUpdate(it) } } } } } // 等待进程结束,获取退出码 val exitCode = process.waitFor() withContext(Dispatchers.Main) { onExtractionComplete(exitCode == 0) } } catch (e: Exception) { e.printStackTrace() withContext(Dispatchers.Main) { onExtractionComplete(false) } } finally { process?.destroy() } } } // 调用示例 fun startExtraction(externalFilesDir: String, password: String) { val source = "$externalFilesDir/meta.7z" val output = "$externalFilesDir/meta" extractWithProgress(source, output, password, onProgressUpdate = { progress -> // 这里更新UI,比如进度条 // progressBar.progress = progress }, onExtractionComplete = { success -> // 处理完成逻辑,比如提示用户 // Toast.makeText(context, if (success) "解压完成" else "解压失败", Toast.LENGTH_SHORT).show() } ) }
关键注意点
- 线程/协程选择:用
Dispatchers.IO处理IO操作(读取流),更新UI必须切换到Dispatchers.Main,避免ANR - 流的关闭:用
use关键字自动关闭BufferedReader,防止资源泄漏 - 异常处理:捕获进程启动、流读取、命令执行中的异常,确保崩溃时能正确回调失败状态
- 权限检查:确保已申请
READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE(Android 13+可能需要更细粒度的权限)
替代方案(如果不想放弃P7ZipApi)
如果P7ZipApi是开源库,你可以修改其executeCommand方法,添加回调参数来传递stdout内容;如果是闭源的,就只能用上面的手动创建进程的方式。
内容的提问来源于stack exchange,提问作者metalex
相关产品推荐
相关产品推荐

