Load a large image from java.io.File doesn't work anymore in 2.0.0-rc01
sirambd opened this issue · comments
Describe the bug
When loading a large image from storage, with the load data(File)
method, it doesn't work anymore knowing that it works well with the io.coil-kt:coil:1.4.0
version, but if you load it from the remote it works
With the same
56MB
image on 1.4.0 it works but not on2.0.0-rc01
.
To Reproduce
- Call
ImageRequest.Builder(context).data(File)
withjava.io.File > 56Mo
This bug happens on all phones and emulators that I could test
Logs/Screenshots
I/RealImageLoader: 🚨 Failed - /storage/emulated/0/Android/media/com.infomaniak.drive/offline_storage/1085402/420132/test/RapidEye_RapidEye_5m_RGB_Altotting_Germany_Agriculture_and_Forestry_2009MAY17_8bits_sub_r_2 copie.jpg - java.lang.IllegalStateException: BitmapFactory returned a null bitmap. Often this means BitmapFactory could not decode the image data read from the input source (e.g. network, disk, or memory) as it's not encoded as a valid image format.
stacktrace
W/System.err: java.lang.IllegalStateException: BitmapFactory returned a null bitmap. Often this means BitmapFactory could not decode the image data read from the input source (e.g. network, disk, or memory) as it's not encoded as a valid image format.
W/System.err: at coil.decode.BitmapFactoryDecoder.decode(BitmapFactoryDecoder.kt:64)
W/System.err: at coil.decode.BitmapFactoryDecoder.access$decode(BitmapFactoryDecoder.kt:24)
W/System.err: at coil.decode.BitmapFactoryDecoder$decode$2$1.invoke(BitmapFactoryDecoder.kt:31)
W/System.err: at coil.decode.BitmapFactoryDecoder$decode$2$1.invoke(BitmapFactoryDecoder.kt:31)
W/System.err: at kotlinx.coroutines.InterruptibleKt.runInterruptibleInExpectedContext(Interruptible.kt:46)
W/System.err: at kotlinx.coroutines.InterruptibleKt.access$runInterruptibleInExpectedContext(Interruptible.kt:1)
W/System.err: at kotlinx.coroutines.InterruptibleKt$runInterruptible$2.invokeSuspend(Interruptible.kt:38)
W/System.err: at kotlinx.coroutines.InterruptibleKt$runInterruptible$2.invoke(Unknown Source:8)
W/System.err: at kotlinx.coroutines.InterruptibleKt$runInterruptible$2.invoke(Unknown Source:4)
W/System.err: at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
W/System.err: at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:157)
W/System.err: at kotlinx.coroutines.BuildersKt.withContext(Unknown Source:1)
W/System.err: at kotlinx.coroutines.InterruptibleKt.runInterruptible(Interruptible.kt:37)
W/System.err: at kotlinx.coroutines.InterruptibleKt.runInterruptible$default(Interruptible.kt:34)
W/System.err: at coil.decode.BitmapFactoryDecoder.decode(BitmapFactoryDecoder.kt:31)
W/System.err: at coil.intercept.EngineInterceptor.decode(EngineInterceptor.kt:199)
W/System.err: at coil.intercept.EngineInterceptor.access$decode(EngineInterceptor.kt:41)
W/System.err: at coil.intercept.EngineInterceptor$execute$executeResult$1.invokeSuspend(EngineInterceptor.kt:127)
W/System.err: at coil.intercept.EngineInterceptor$execute$executeResult$1.invoke(Unknown Source:8)
W/System.err: at coil.intercept.EngineInterceptor$execute$executeResult$1.invoke(Unknown Source:4)
W/System.err: at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
W/System.err: at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:165)
W/System.err: at kotlinx.coroutines.BuildersKt.withContext(Unknown Source:1)
W/System.err: at coil.intercept.EngineInterceptor.execute(EngineInterceptor.kt:126)
W/System.err: at coil.intercept.EngineInterceptor.access$execute(EngineInterceptor.kt:41)
W/System.err: at coil.intercept.EngineInterceptor$intercept$2.invokeSuspend(EngineInterceptor.kt:75)
W/System.err: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
W/System.err: at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
W/System.err: at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
W/System.err: at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
W/System.err: at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
W/System.err: at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
W/System.err: at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
W/System.err: at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
call
val timer = createRefreshTimer(milliseconds = 400) { noThumbnailLayout?.isVisible = true }.start()
val offlineFile = if (file.isOffline) getOfflineFile() else null // a `java.io.File` picture
return ImageRequest.Builder(requireContext())
.data(offlineFile ?: file.imagePreview())
.listener(
onError = { _, _ ->
fileName?.text = file.name
previewDescription?.isVisible = true
bigOpenWithButton?.isVisible = true
imageView?.isGone = true
},
onSuccess = { _, _ ->
timer.cancel()
noThumbnailLayout?.isGone = true
},
)
.build()
imageLoader
override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(applicationContext)
.crossfade(true)
.components {
add(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) ImageDecoderDecoder.Factory() else GifDecoder.Factory())
}
.okHttpClient {
OkHttpClient.Builder().apply {
addInterceptor(Interceptor { chain ->
var request = chain.request()
if (request.url.toString().contains(DRIVE_API) || request.url.toString().contains(INFOMANIAK_API)) {
request = request.newBuilder().headers(HttpUtils.getHeaders()).removeHeader("Cache-Control").build()
}
chain.proceed(request)
})
addInterceptor(TokenInterceptor(tokenInterceptorListener()))
authenticator(TokenAuthenticator(tokenInterceptorListener()))
if (com.infomaniak.lib.core.BuildConfig.DEBUG) {
addNetworkInterceptor(StethoInterceptor())
}
}.build()
}
.memoryCache {
MemoryCache.Builder(applicationContext)
.maxSizePercent(MEMORY_CACHE_PERCENT)
.build()
}
.diskCache {
DiskCache.Builder()
.directory(applicationContext.cacheDir.resolve("coil_cache"))
.maxSizePercent(DISK_CACHE_PERCENT)
.build()
}
.build()
}
Version
io.coil-kt:coil:2.0.0-rc01
Thanks for the report. Could you post the failing image in this thread? You can also email me at colin<at>colinwhite.me
if you'd like to keep the image private.
@colinrtwhite Here is an example of a failed image
https://kdrive.1-fat-mail.ch/app/share/140946/c86066ff-9318-48b7-bc1f-ccd554146b05
@sirambd Thanks for the sample image! I believe this is related to this change in 2.x. Setting a size
for the request (e.g. ImageRequest.Builder.size(2000)
) will ensure that you don't load the image at 2000x2000 pixels instead of full-size. This image is ~9000x5000, which is too large for Android to decode without resizing (~4000x4000 is the max).
EDIT: In hindsight this change seems unexpected and could cause issues when upgrading. Keep an eye out for 2.0.0-rc02
for a fix.