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

Android Kotlin Jetpack Compose:特定设备图库图片旋转异常求助

解决Jetpack Compose中Android 9设备图片旋转异常问题

在Android 9(API 28)及以下版本,MediaStore.Images.Media.getBitmap不会自动读取并应用图片的Exif旋转元数据,这就是富士通901FJ设备上部分图库图片显示旋转/倒置的原因。以下是针对Kotlin代码的修复方案:

1. 添加Exif旋转角度读取函数

这个函数从图片的Exif信息中提取正确的旋转角度:

import android.media.ExifInterface
import android.content.ContentResolver
import android.net.Uri

fun Uri.getImageRotationAngle(contentResolver: ContentResolver): Int {
    return kotlin.runCatching {
        contentResolver.openInputStream(this)?.use { inputStream ->
            val exif = ExifInterface(inputStream)
            when (exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL
            )) {
                ExifInterface.ORIENTATION_ROTATE_90 -> 90
                ExifInterface.ORIENTATION_ROTATE_180 -> 180
                ExifInterface.ORIENTATION_ROTATE_270 -> 270
                else -> 0
            }
        }
    }.getOrDefault(0)
}

2. 添加Bitmap旋转工具函数

根据读取到的角度修正Bitmap方向:

import android.graphics.Bitmap
import android.graphics.Matrix

fun Bitmap.rotate(degrees: Int): Bitmap {
    if (degrees == 0) return this
    val matrix = Matrix().apply { postRotate(degrees.toFloat()) }
    return Bitmap.createBitmap(this, 0, 0, width, height, matrix, true)
}

3. 修改图片加载逻辑

更新图库选择后的处理代码,先修正旋转再缩放:

val galleryLauncher =
    rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
        uri?.let {
            val originalBitmap = it.getBitmapOrNull(context.contentResolver)
            originalBitmap?.let { bitmap ->
                val rotationAngle = it.getImageRotationAngle(context.contentResolver)
                val rotatedBitmap = bitmap.rotate(rotationAngle)
                // 缩放并更新状态
                imageBitmap = Bitmap.createScaledBitmap(rotatedBitmap, 120, 120, true)
                // 回收临时Bitmap避免内存泄漏
                if (bitmap !== rotatedBitmap) {
                    bitmap.recycle()
                }
                rotatedBitmap.recycle()
            }
        }
    }

额外注意事项

  • 针对Android 9设备,确保已在Manifest中添加READ_EXTERNAL_STORAGE权限,并在运行时请求该权限(如果图片来自外部存储)。
  • 若将旋转逻辑整合到getBitmapOrNull函数中,需注意在API 29+版本中,ImageDecoder已经自动处理了Exif旋转,无需重复操作,所以可以在函数内做版本判断:
fun Uri.getBitmapOrNull(contentResolver: ContentResolver): Bitmap? {
    return kotlin.runCatching {
        val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            val source = ImageDecoder.createSource(contentResolver, this)
            ImageDecoder.decodeBitmap(source)
        } else {
            MediaStore.Images.Media.getBitmap(contentResolver, this)
        }
        // 仅在Android 9及以下处理旋转
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            val rotationAngle = getImageRotationAngle(contentResolver)
            bitmap.rotate(rotationAngle)
        } else {
            bitmap
        }
    }.getOrNull()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:47:54