diff --git a/coil-base/api/coil-base.api b/coil-base/api/coil-base.api index da8807691a..39c616c254 100644 --- a/coil-base/api/coil-base.api +++ b/coil-base/api/coil-base.api @@ -156,6 +156,7 @@ public abstract interface annotation class coil/annotation/ExperimentalCoilApi : public final class coil/decode/AssetMetadata : coil/decode/ImageSource$Metadata { public fun (Ljava/lang/String;)V public final fun getFileName ()Ljava/lang/String; + public final fun getFilePath ()Ljava/lang/String; } public final class coil/decode/BitmapFactoryDecoder : coil/decode/Decoder { diff --git a/coil-base/src/main/java/coil/decode/ImageSource.kt b/coil-base/src/main/java/coil/decode/ImageSource.kt index 31b8b84269..f92de2904c 100644 --- a/coil-base/src/main/java/coil/decode/ImageSource.kt +++ b/coil-base/src/main/java/coil/decode/ImageSource.kt @@ -172,10 +172,17 @@ sealed class ImageSource : Closeable { } /** - * Metadata containing the [fileName] of an Android asset. + * Metadata containing the [filePath] of an Android asset. */ @ExperimentalCoilApi -class AssetMetadata(val fileName: String) : ImageSource.Metadata() +class AssetMetadata(val filePath: String) : ImageSource.Metadata() { + + @Deprecated( + message = "Migrate to filePath as it supports assets inside subfolders.", + level = DeprecationLevel.ERROR + ) + val fileName: String get() = filePath.substringAfter('/') +} /** * Metadata containing the [uri] of a `content` URI. diff --git a/coil-base/src/main/java/coil/fetch/AssetUriFetcher.kt b/coil-base/src/main/java/coil/fetch/AssetUriFetcher.kt index e4f33d87d2..9c656e86b4 100644 --- a/coil-base/src/main/java/coil/fetch/AssetUriFetcher.kt +++ b/coil-base/src/main/java/coil/fetch/AssetUriFetcher.kt @@ -24,7 +24,7 @@ internal class AssetUriFetcher( source = ImageSource( source = options.context.assets.open(path).source().buffer(), context = options.context, - metadata = AssetMetadata(data.lastPathSegment!!) + metadata = AssetMetadata(path) ), mimeType = MimeTypeMap.getSingleton().getMimeTypeFromUrl(path), dataSource = DataSource.DISK diff --git a/coil-gif/src/main/java/coil/decode/ImageDecoderDecoder.kt b/coil-gif/src/main/java/coil/decode/ImageDecoderDecoder.kt index 6a43c67dc1..6062990486 100644 --- a/coil-gif/src/main/java/coil/decode/ImageDecoderDecoder.kt +++ b/coil-gif/src/main/java/coil/decode/ImageDecoderDecoder.kt @@ -108,7 +108,7 @@ class ImageDecoderDecoder @JvmOverloads constructor( val metadata = metadata if (metadata is AssetMetadata) { - return ImageDecoder.createSource(options.context.assets, metadata.fileName) + return ImageDecoder.createSource(options.context.assets, metadata.filePath) } if (metadata is ContentMetadata) { return ImageDecoder.createSource(options.context.contentResolver, metadata.uri) diff --git a/coil-video/src/androidTest/assets/nested/video.mp4 b/coil-video/src/androidTest/assets/nested/video.mp4 new file mode 100644 index 0000000000..3ce062e77b Binary files /dev/null and b/coil-video/src/androidTest/assets/nested/video.mp4 differ diff --git a/coil-video/src/androidTest/java/coil/decode/VideoFrameDecoderTest.kt b/coil-video/src/androidTest/java/coil/decode/VideoFrameDecoderTest.kt index e78e8551f4..464c54ae44 100644 --- a/coil-video/src/androidTest/java/coil/decode/VideoFrameDecoderTest.kt +++ b/coil-video/src/androidTest/java/coil/decode/VideoFrameDecoderTest.kt @@ -34,7 +34,7 @@ class VideoFrameDecoderTest { @Test fun noSetFrameTime() = runTest { - // MediaMetadataRetriever.getFrameAtTime does not work on the emulator pre-API 23. + // MediaMetadataRetriever does not work on the emulator pre-API 23. assumeTrue(SDK_INT >= 23) val result = VideoFrameDecoder( @@ -55,7 +55,7 @@ class VideoFrameDecoderTest { @Test fun specificFrameTime() = runTest { - // MediaMetadataRetriever.getFrameAtTime does not work on the emulator pre-API 23. + // MediaMetadataRetriever does not work on the emulator pre-API 23. assumeTrue(SDK_INT >= 23) val result = VideoFrameDecoder( @@ -81,7 +81,7 @@ class VideoFrameDecoderTest { @Test fun specificFramePercent() = runTest { - // MediaMetadataRetriever.getFrameAtTime does not work on the emulator pre-API 23. + // MediaMetadataRetriever does not work on the emulator pre-API 23. assumeTrue(SDK_INT >= 23) val result = VideoFrameDecoder( @@ -107,7 +107,7 @@ class VideoFrameDecoderTest { @Test fun rotation() = runTest { - // MediaMetadataRetriever.getFrameAtTime does not work on the emulator pre-API 23. + // MediaMetadataRetriever does not work on the emulator pre-API 23. assumeTrue(SDK_INT >= 23) val result = VideoFrameDecoder( @@ -125,4 +125,28 @@ class VideoFrameDecoderTest { val expected = context.decodeBitmapAsset("video_frame_rotated.jpg") actual.assertIsSimilarTo(expected, threshold = 0.97) } + + /** Regression test: https://github.com/coil-kt/coil/issues/1482 */ + @Test + fun nestedAsset() = runTest { + // MediaMetadataRetriever does not work on the emulator pre-API 23. + assumeTrue(SDK_INT >= 23) + + val path = "nested/video.mp4" + val result = VideoFrameDecoder( + source = ImageSource( + source = context.assets.open(path).source().buffer(), + context = context, + metadata = AssetMetadata(path) + ), + options = Options(context) + ).decode() + + val actual = (result.drawable as? BitmapDrawable)?.bitmap + assertNotNull(actual) + assertFalse(result.isSampled) + + val expected = context.decodeBitmapAsset("video_frame_1.jpg") + actual.assertIsSimilarTo(expected) + } } diff --git a/coil-video/src/main/java/coil/decode/VideoFrameDecoder.kt b/coil-video/src/main/java/coil/decode/VideoFrameDecoder.kt index 619ca97cb4..f05293ed9e 100644 --- a/coil-video/src/main/java/coil/decode/VideoFrameDecoder.kt +++ b/coil-video/src/main/java/coil/decode/VideoFrameDecoder.kt @@ -182,7 +182,7 @@ class VideoFrameDecoder( private fun MediaMetadataRetriever.setDataSource(source: ImageSource) { when (val metadata = source.metadata) { is AssetMetadata -> { - options.context.assets.openFd(metadata.fileName).use { + options.context.assets.openFd(metadata.filePath).use { setDataSource(it.fileDescriptor, it.startOffset, it.length) } }