You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Android多图自定义压缩率压缩并自动打包Zip开发求助

开发切入点拆解

1. 批量选择内部存储的JPG图片

  • 用Intent.ACTION_OPEN_DOCUMENT搭配EXTRA_ALLOW_MULTIPLE实现多选,Android 13及以上申请READ_MEDIA_IMAGES权限,低版本申请READ_EXTERNAL_STORAGE权限
  • 处理返回的Intent时,通过clipData获取所有选中图片的Uri,用ContentResolver打开输入流(适配Android 10+存储沙箱,避免直接操作文件路径)
  • 过滤出后缀为.jpg/.jpeg的文件,可通过Uri查询MediaStore获取文件名判断

2. 自定义压缩率的批量图片压缩

  • 核心依赖BitmapFactory和Bitmap.compress(),从EditText获取压缩率(转成0-100的Int值,0压缩比最高,100无损)
  • 提前计算采样率避免OOM:用BitmapFactory.Options的inJustDecodeBounds获取原图片尺寸,根据目标尺寸(比如1080P)计算inSampleSize
  • 用线程池或Coroutines在后台执行批量压缩,避免ANR;压缩后的图片临时存放在App私有目录(getExternalFilesDir(Environment.DIRECTORY_PICTURES)),无需额外权限

示例压缩代码片段:

fun compressImage(inputStream: InputStream, quality: Int, outputFile: File) {
    val options = BitmapFactory.Options().apply {
        inJustDecodeBounds = true
        BitmapFactory.decodeStream(inputStream, null, this)
        inSampleSize = calculateInSampleSize(this, 1080, 1080)
        inJustDecodeBounds = false
    }
    inputStream.reset()
    val bitmap = BitmapFactory.decodeStream(inputStream, null, options)
    bitmap?.compress(Bitmap.CompressFormat.JPEG, quality, FileOutputStream(outputFile))
    bitmap?.recycle()
}

private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
    val (height, width) = options.outHeight to options.outWidth
    var inSampleSize = 1
    if (height > reqHeight || width > reqWidth) {
        val (halfHeight, halfWidth) = height / 2 to width / 2
        while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
            inSampleSize *= 2
        }
    }
    return inSampleSize
}

3. 压缩图片打包Zip

  • 用Java原生ZipOutputStream实现,遍历压缩后的临时文件列表,逐个写入Zip包
  • 同样在后台线程执行,避免阻塞主线程
  • 保存路径优先选公共下载目录(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)),Android 10+需要申请MANAGE_EXTERNAL_STORAGE权限,或用MediaStore写入更合规

示例Zip打包代码片段:

fun zipFiles(files: List<File>, zipOutputFile: File) {
    ZipOutputStream(FileOutputStream(zipOutputFile)).use { zos ->
        files.forEach { file ->
            FileInputStream(file).use { fis ->
                val entry = ZipEntry(file.name)
                zos.putNextEntry(entry)
                fis.copyTo(zos, 8192)
                zos.closeEntry()
            }
        }
    }
}

4. 关键注意事项

  • 权限处理:动态申请必要权限,适配不同Android版本的存储规则
  • 后台任务:用Coroutines管理异步任务,更新UI切换到主线程
  • 异常捕获:处理文件流、权限相关的IOException,给用户明确错误提示
  • 临时文件:打包完成后删除压缩后的临时图片,释放存储

内容的提问来源于stack exchange,提问作者Flamingo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:55:07