music: attempt to handle bad DISPLAY_NAME [#120]
Add recovery code to the music indexer in the case that Android doesn't provide the DISPLAY_NAME field. Nominally this should never happen, but OEMs will OEM and apparently this does happen on some devices. Try to recover by grokking DATA for a file name.
This commit is contained in:
parent
0b9141d474
commit
28cedd1240
4 changed files with 21 additions and 13 deletions
|
@ -10,6 +10,7 @@
|
||||||
#### What's Fixed
|
#### What's Fixed
|
||||||
- Fixed incorrect ellipsizing on song items
|
- Fixed incorrect ellipsizing on song items
|
||||||
- Fixed a variety of esoteric crashes with queue state
|
- Fixed a variety of esoteric crashes with queue state
|
||||||
|
- Fixed music indexing error when the OS would not provide a file name
|
||||||
|
|
||||||
#### What's Changed
|
#### What's Changed
|
||||||
- Audio focus is no longer configurable
|
- Audio focus is no longer configurable
|
||||||
|
|
|
@ -135,7 +135,8 @@ object Indexer {
|
||||||
* songs are properly linked up.
|
* songs are properly linked up.
|
||||||
*/
|
*/
|
||||||
private fun loadSongs(context: Context): List<Song> {
|
private fun loadSongs(context: Context): List<Song> {
|
||||||
val blacklistDatabase = ExcludedDatabase.getInstance(context)
|
val excludedDatabase = ExcludedDatabase.getInstance(context)
|
||||||
|
val paths = excludedDatabase.readPaths()
|
||||||
var selector = "${MediaStore.Audio.Media.IS_MUSIC}=1"
|
var selector = "${MediaStore.Audio.Media.IS_MUSIC}=1"
|
||||||
val args = mutableListOf<String>()
|
val args = mutableListOf<String>()
|
||||||
|
|
||||||
|
@ -143,9 +144,7 @@ object Indexer {
|
||||||
// DATA was deprecated in Android 10, but it was un-deprecated in Android 12L,
|
// DATA was deprecated in Android 10, but it was un-deprecated in Android 12L,
|
||||||
// so it's probably okay to use it. The only reason we would want to use
|
// so it's probably okay to use it. The only reason we would want to use
|
||||||
// another method is for external partitions support, but there is no demand for that.
|
// another method is for external partitions support, but there is no demand for that.
|
||||||
// TODO: Determine if grokking the actual DATA value outside of SQL is more or less
|
for (path in excludedDatabase.readPaths()) {
|
||||||
// efficient than the current system
|
|
||||||
for (path in blacklistDatabase.readPaths()) {
|
|
||||||
selector += " AND ${MediaStore.Audio.Media.DATA} NOT LIKE ?"
|
selector += " AND ${MediaStore.Audio.Media.DATA} NOT LIKE ?"
|
||||||
args += "$path%" // Append % so that the selector properly detects children
|
args += "$path%" // Append % so that the selector properly detects children
|
||||||
}
|
}
|
||||||
|
@ -164,7 +163,8 @@ object Indexer {
|
||||||
MediaStore.Audio.AudioColumns.ALBUM,
|
MediaStore.Audio.AudioColumns.ALBUM,
|
||||||
MediaStore.Audio.AudioColumns.ALBUM_ID,
|
MediaStore.Audio.AudioColumns.ALBUM_ID,
|
||||||
MediaStore.Audio.AudioColumns.ARTIST,
|
MediaStore.Audio.AudioColumns.ARTIST,
|
||||||
AUDIO_COLUMN_ALBUM_ARTIST),
|
AUDIO_COLUMN_ALBUM_ARTIST,
|
||||||
|
MediaStore.Audio.AudioColumns.DATA),
|
||||||
selector,
|
selector,
|
||||||
args.toTypedArray(),
|
args.toTypedArray(),
|
||||||
null)
|
null)
|
||||||
|
@ -182,11 +182,22 @@ object Indexer {
|
||||||
cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.ALBUM_ID)
|
cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.ALBUM_ID)
|
||||||
val artistIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.ARTIST)
|
val artistIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.ARTIST)
|
||||||
val albumArtistIndex = cursor.getColumnIndexOrThrow(AUDIO_COLUMN_ALBUM_ARTIST)
|
val albumArtistIndex = cursor.getColumnIndexOrThrow(AUDIO_COLUMN_ALBUM_ARTIST)
|
||||||
|
val dataIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.DATA)
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
val id = cursor.getLong(idIndex)
|
val id = cursor.getLong(idIndex)
|
||||||
val title = cursor.getString(titleIndex)
|
val title = cursor.getString(titleIndex)
|
||||||
val fileName = cursor.getString(fileIndex)
|
|
||||||
|
// Try to use the DISPLAY_NAME field to obtain a (probably sane) file name
|
||||||
|
// from the android system. Once gain though, OEM issues get in our way and
|
||||||
|
// this field isn't available on some platforms. In that case, see if we can
|
||||||
|
// grok a file name from the DATA field.
|
||||||
|
val fileName =
|
||||||
|
cursor.getStringOrNull(fileIndex)
|
||||||
|
?: cursor.getStringOrNull(dataIndex)?.run {
|
||||||
|
substringAfterLast('/', "").ifEmpty { null }
|
||||||
|
}
|
||||||
|
?: MediaStore.UNKNOWN_STRING
|
||||||
|
|
||||||
// The TRACK field is for some reason formatted as DTTT, where D is the disk
|
// The TRACK field is for some reason formatted as DTTT, where D is the disk
|
||||||
// and T is the track. This is dumb and insane and forces me to mangle track
|
// and T is the track. This is dumb and insane and forces me to mangle track
|
||||||
|
@ -224,11 +235,6 @@ object Indexer {
|
||||||
|
|
||||||
val albumArtist = cursor.getStringOrNull(albumArtistIndex)
|
val albumArtist = cursor.getStringOrNull(albumArtistIndex)
|
||||||
|
|
||||||
// Note: Directory parsing is currently disabled until artist images are added.
|
|
||||||
// val dirs = cursor.getStringOrNull(dataIndex)?.run {
|
|
||||||
// substringBeforeLast("/", "").ifEmpty { null }
|
|
||||||
// }
|
|
||||||
|
|
||||||
songs.add(
|
songs.add(
|
||||||
Song(
|
Song(
|
||||||
title,
|
title,
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
style="@style/Widget.Auxio.Image.Small"
|
style="@style/Widget.Auxio.Image.Small"
|
||||||
android:src="@drawable/ic_song"
|
android:src="@drawable/ic_song"
|
||||||
android:scaleType="matrix"
|
android:scaleType="matrix"
|
||||||
|
tools:src="@null"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/song_track"
|
app:layout_constraintBottom_toBottomOf="@+id/song_track"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/song_track"
|
app:layout_constraintEnd_toEndOf="@+id/song_track"
|
||||||
app:layout_constraintStart_toStartOf="@+id/song_track"
|
app:layout_constraintStart_toStartOf="@+id/song_track"
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textAppearance="@style/TextAppearance.Auxio.BodyLarge"
|
android:textAppearance="@style/TextAppearance.Auxio.BodyLarge"
|
||||||
android:textColor="@color/sel_on_cover_bg"
|
android:textColor="@color/sel_on_cover_bg"
|
||||||
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/song_name"
|
app:layout_constraintEnd_toStartOf="@+id/song_name"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
<org.oxycblt.auxio.coil.StyledImageView
|
<org.oxycblt.auxio.coil.StyledImageView
|
||||||
android:id="@+id/disc_item"
|
android:id="@+id/disc_item"
|
||||||
style="@style/Widget.Auxio.Image.Small"
|
style="@style/Widget.Auxio.Image.Small"
|
||||||
android:layout_width="@dimen/size_cover_compact"
|
android:scaleType="matrix"
|
||||||
android:scaleType="center"
|
|
||||||
android:src="@drawable/ic_album"
|
android:src="@drawable/ic_album"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
Loading…
Reference in a new issue