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
相关产品推荐
相关产品推荐

