Optimize quality cover loading
Make the loading process for higher-quality covers far more efficent and elegant compared to the previous method.
This commit is contained in:
parent
bc1992de4e
commit
6c37ba7d3e
2 changed files with 42 additions and 22 deletions
|
@ -1,25 +1,28 @@
|
|||
package org.oxycblt.auxio.coil
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import android.media.MediaMetadataRetriever
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import android.net.Uri
|
||||
import coil.bitmap.BitmapPool
|
||||
import coil.decode.DataSource
|
||||
import coil.decode.Options
|
||||
import coil.fetch.DrawableResult
|
||||
import coil.fetch.FetchResult
|
||||
import coil.fetch.Fetcher
|
||||
import coil.fetch.SourceResult
|
||||
import coil.size.Size
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.toURI
|
||||
import java.lang.Exception
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStream
|
||||
|
||||
/**
|
||||
* A [Fetcher] for fetching high-quality embedded covers instead of the compressed covers, albeit
|
||||
* at the cost of load time & caching.
|
||||
* at the cost of load time & memory usage.
|
||||
*/
|
||||
class QualityCoverFetcher(private val context: Context) : Fetcher<Song> {
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
override suspend fun fetch(
|
||||
pool: BitmapPool,
|
||||
data: Song,
|
||||
|
@ -27,29 +30,46 @@ class QualityCoverFetcher(private val context: Context) : Fetcher<Song> {
|
|||
options: Options
|
||||
): FetchResult {
|
||||
val extractor = MediaMetadataRetriever()
|
||||
val stream: InputStream?
|
||||
val uri: Uri
|
||||
|
||||
extractor.setDataSource(context, data.id.toURI())
|
||||
extractor.use { extractor ->
|
||||
extractor.setDataSource(context, data.id.toURI())
|
||||
val cover = extractor.embeddedPicture
|
||||
|
||||
val bitmap = try {
|
||||
val bytes = extractor.embeddedPicture
|
||||
stream = if (cover != null) {
|
||||
uri = data.id.toURI()
|
||||
|
||||
if (bytes != null) {
|
||||
BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
|
||||
ByteArrayInputStream(cover)
|
||||
} else {
|
||||
throw Exception()
|
||||
// Fallback to the compressed cover if the cover loading failed.
|
||||
uri = data.album.coverUri
|
||||
|
||||
// Blocking call, but coil is on a background thread so it doesn't matter
|
||||
context.contentResolver.openInputStream(data.album.coverUri)
|
||||
}
|
||||
|
||||
stream?.use {
|
||||
return SourceResult(
|
||||
source = stream.source().buffer(),
|
||||
mimeType = context.contentResolver.getType(uri),
|
||||
dataSource = DataSource.DISK
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
extractor.release()
|
||||
error("Likely no album art for this item.")
|
||||
} finally {
|
||||
extractor.release()
|
||||
}
|
||||
|
||||
return DrawableResult(
|
||||
drawable = bitmap.toDrawable(context.resources),
|
||||
isSampled = false,
|
||||
dataSource = DataSource.DISK
|
||||
)
|
||||
// If we are here, the extractor likely failed so instead attempt to return the compressed
|
||||
// cover instead.
|
||||
context.contentResolver.openInputStream(data.album.coverUri)?.use { stream ->
|
||||
return SourceResult(
|
||||
source = stream.source().buffer(),
|
||||
mimeType = context.contentResolver.getType(uri),
|
||||
dataSource = DataSource.DISK
|
||||
)
|
||||
}
|
||||
|
||||
// If even that failed, then error out entirely.
|
||||
error("Likely no bitmap for this song/album.")
|
||||
}
|
||||
|
||||
// Group bitmaps by their album so that caching is more efficent
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
<string name="setting_show_covers_desc">Turn off to save memory usage</string>
|
||||
|
||||
<string name="setting_quality_covers">Ignore MediaStore covers</string>
|
||||
<string name="setting_quality_covers_desc">Results in higher quality album covers at the cost of slower loading times and higher memory usage</string>
|
||||
<string name="setting_quality_covers_desc">Results in higher quality album covers, but causes slower loading and higher memory usage</string>
|
||||
|
||||
<string name="setting_use_alt_action">Use alternate notification action</string>
|
||||
<string name="setting_use_alt_loop">Prefer repeat mode action</string>
|
||||
|
|
Loading…
Reference in a new issue