반응형
Fatal Exception: java.lang.IllegalArgumentException
RemoteViews for widget update exceeds maximum bitmap memory usage (used: 16216160, max: 15940800)
위와 같은 에러가 간혹 Widget에서 Bitmap을 사용할 때 발생합니다.
이전에 관련된 글을 작성했으나 여전히 재발하는 경우가 있어서 더 강화된 로직을 문서를 참고하여 구성했습니다.
거대한 비트맵 처리에 대해서 아래 공식 문서에서 처리 로직을 제안해주고 있습니다.
https://developer.android.com/topic/performance/graphics/load-bitmap?hl=ko
큰 비트맵을 효율적으로 로드 | App quality | Android Developers
이미지의 모양과 크기는 다양합니다. 많은 경우 이미지는 일반적인 애플리케이션 사용자 인터페이스(UI)에서 요구하는 크기보다 큽니다. 예를 들어, 시스템 Gallery 애플리케이션은 Android 기기의
developer.android.com
너비와 높이 계산만을 위한 옵션을 설정하고, 첫 번째 디코딩을 진행합니다.
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
BitmapFactory.decodeFile(file.absolutePath, options)
이후, Sample Size를 통해 적절한 크기로 리사이징 및 샘플링이 가능합니다.
특정 한계 값 아래로 Bitmap Sample Size가 형성되도록 함수를 구성합니다.
전 위젯 생성 시 선언한 기본 가로 세로 값을 활용했습니다.
private fun calculateInSampleSize(
options: BitmapFactory.Options,
widgetHeight: Int,
widgetWidth: Int): Int
{
val height = options.outHeight
val width = options.outWidth
var inSampleSize = 1
if (height > widgetHeight || width > widgetWidth) {
val halfHeight = height / 2
val halfWidth = width / 2
while (halfHeight / inSampleSize >= widgetHeight
|| halfWidth / inSampleSize >= widgetWidth
) { inSampleSize *= 2 }
}
return inSampleSize
}
너비와 높이를 계산한 이후 옵션의 'inJsutDecodeBounds'를 다시 false 하여 최종 디코딩을 진행합니다.
options.inSampleSize = calculateInSampleSize(options, width, height)
options.inJustDecodeBounds = false
BitmapFactory.decodeFile(file.absolutePath, options)
전체 코드 ->
val bitmap = try {
val file = File("${context.filesDir.absolutePath}/$example")
if (file.exists()) {
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
BitmapFactory.decodeFile(file.absolutePath, options)
options.inSampleSize = calculateInSampleSize(options, width, height)
options.inJustDecodeBounds = false
BitmapFactory.decodeFile(file.absolutePath, options)
} else {
null
}
} catch (e: Exception) {
e.printStackTrace()
null
} ?: return
반응형