Sie ruft zuerst die Song-ID über MediaStore ab und sendet fd an TagLib, das sie dupliziert und zum Öffnen eines Streams verwendet, um die Metadaten und Audioeigenschaften abzurufen.
Dies gibt eine Zuordnung von und einem IntArray der Größe 4 zurück.
Dies wird für jede von der zurückgegebene ID aufgerufen MediaStore-Abfrage.
Die ersten 1700 Songs dauern ca. 700 ms pro 100 Songs, aber alle 100 danach dauern 23 Sekunden und erhöhen sich alle 100 auf ca. 60 Sekunden.
Diese Methode wird auf Dispatchers IO ausgeführt.
Was kann ich tun, um dies zu reduzieren?
Dieser vollständige Scan wird beim ersten Start der App durchgeführt Nicht wirklich besorgniserregend.
Allerdings dauert ein vollständiger Scan bei über 7900 Songs etwa 18 Minuten.
MediaStore-Scan
Code: Select all
fun getAudioFilesViaMediaStore(): List {
//.nomedia affected
val musicUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Audio.Media._ID)
val audioList = mutableListOf()
//TODO replace placeholder path
val audioCursor = contentResolver.query(
musicUri,
projection,
"${MediaStore.Audio.Media.RELATIVE_PATH} LIKE ?",
arrayOf("%Music%"),
null
) ?: return emptyList()
audioCursor.use { cursor ->
val idColumn: Int = audioCursor.getColumnIndex(MediaStore.Audio.AudioColumns._ID)
cursor.apply {
if (count == 0) Log.d("Cursor", "get cursor data: Cursor is empty.")
else {
while (cursor.moveToNext()) {
try {
val iD = cursor.getLong(idColumn)
val song = getSongDetailsTagLib(iD)
if (song != null) audioList += song
} catch (e: Exception) {
Log.e("Cursor read", "ERR", e)
}
}
}
}
}
return audioList
}
Code: Select all
fun getSongDetailsTagLib(id: Long): Song? {
val uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id)
val pfd = contentResolver.openFileDescriptor(uri, "r") ?: return null
val fd = pfd.detachFd()
val prop: IntArray = TagLib.getAudioProperties(fd)
val metadata: HashMap = TagLib.getMetadata(fd)
val title = metadata["TITLE"]?.firstOrNull()?.takeIf { it.isNotBlank() } ?: ""
val artist = metadata["ARTIST"]?.firstOrNull()?.takeIf { it.isNotBlank() } ?: ""
val album = metadata["ALBUM"]?.firstOrNull()?.takeIf { it.isNotBlank() } ?: ""
//etcetc
pfd.close()
return Song(
title = title,
artist = artist,
iD = id
)
}
Code: Select all
lifecycleScope.launch(Dispatchers.IO) {
val audioList = getAudioFilesViaMediaStore()
}
Mobile version