Skip to content

Commit ae34d35

Browse files
committed
refactor: further address code health issues in media and UI components
- Consolidate MediaStore logic in ArtResolver. - Fix global conditionals in GramophonePlaybackService. - Refactor ViewPagerFragment.onCreateView for better modularity. - Reduce argument count in LibraryTreeLoader using MediaItemConfig. Continuing cleanup based on CodeScene feedback.
1 parent 8e7b3ab commit ae34d35

4 files changed

Lines changed: 305 additions & 299 deletions

File tree

app/src/main/java/org/akanework/gramophone/logic/GramophonePlaybackService.kt

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -264,55 +264,58 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
264264
else
265265
customCommands[0]
266266

267-
private val timer: Runnable = Runnable {
267+
private val timer = Runnable { handleTimerExpired() }
268+
269+
private fun handleTimerExpired() {
268270
if (timerPauseOnEnd) {
269-
endedWorkaroundPlayer!!.exoPlayer.pauseAtEndOfMediaItems = true
271+
endedWorkaroundPlayer?.exoPlayer?.pauseAtEndOfMediaItems = true
270272
} else {
271-
controller!!.pause()
273+
controller?.pause()
272274
}
273275
timerDuration = null
274276
}
277+
275278
private var timerPauseOnEnd = false
276279
private var timerDuration: Long? = null
277280
set(value) {
278281
field = value
279-
if (value != null && value > 0) {
280-
handler.postDelayed(timer, value - SystemClock.elapsedRealtime())
281-
} else {
282-
handler.removeCallbacks(timer)
283-
}
284-
mediaSession!!.broadcastCustomCommand(
285-
SessionCommand(SERVICE_TIMER_CHANGED, Bundle.EMPTY),
286-
Bundle.EMPTY
287-
)
282+
updateTimerSchedule(value)
283+
mediaSession?.broadcastCustomCommand(SessionCommand(SERVICE_TIMER_CHANGED, Bundle.EMPTY), Bundle.EMPTY)
288284
}
289285

286+
private fun updateTimerSchedule(value: Long?) {
287+
handler.removeCallbacks(timer)
288+
if (value != null && value > 0) {
289+
handler.postDelayed(timer, value - SystemClock.elapsedRealtime())
290+
}
291+
}
292+
290293
private val seekReceiver = object : BroadcastReceiver() {
291294
override fun onReceive(context: Context, intent: Intent) {
292-
val to =
293-
intent.extras?.getLong("seekTo", C.INDEX_UNSET.toLong()) ?: C.INDEX_UNSET.toLong()
294-
if (to != C.INDEX_UNSET.toLong())
295+
val to = intent.extras?.getLong("seekTo", C.INDEX_UNSET.toLong()) ?: C.INDEX_UNSET.toLong()
296+
if (to != C.INDEX_UNSET.toLong()) {
295297
controller?.seekTo(to)
298+
}
296299
}
297300
}
298301

299302
private val btReceiver = object : BroadcastReceiver() {
300303
override fun onReceive(context: Context, intent: Intent) {
301-
if (intent.action.equals("android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED") &&
302-
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O /* before 8, only sbc was supported */
304+
if (intent.action == "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" &&
305+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
303306
) {
304-
btInfo = BtCodecInfo.fromCodecConfig(
305-
@SuppressLint("NewApi") IntentCompat.getParcelableExtra(
306-
intent,
307-
"android.bluetooth.extra.CODEC_STATUS",
308-
BluetoothCodecStatus::class.java
309-
)?.codecConfig
310-
)
311-
Log.d(TAG, "new bluetooth codec config $btInfo")
307+
handleBluetoothCodecChange(intent)
312308
}
313309
}
314310
}
315311

312+
@SuppressLint("NewApi")
313+
private fun handleBluetoothCodecChange(intent: Intent) {
314+
val status = IntentCompat.getParcelableExtra(intent, "android.bluetooth.extra.CODEC_STATUS", BluetoothCodecStatus::class.java)
315+
btInfo = BtCodecInfo.fromCodecConfig(status?.codecConfig)
316+
Log.d(TAG, "new bluetooth codec config $btInfo")
317+
}
318+
316319
override fun onCreate() {
317320
Log.i(TAG, "+onCreate()")
318321
super.onCreate()
@@ -1229,7 +1232,7 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
12291232

12301233
private fun refreshMediaButtonCustomLayout() {
12311234
val isEmpty = controller?.currentTimeline?.isEmpty != false
1232-
mediaSession!!.connectedControllers.forEach {
1235+
mediaSession?.connectedControllers?.forEach {
12331236
if (mediaSession!!.isMediaNotificationController(it)
12341237
|| mediaSession!!.isAutoCompanionController(it)
12351238
|| mediaSession!!.isAutomotiveController(it)

app/src/main/java/org/akanework/gramophone/logic/LibraryTreeLoader.kt

Lines changed: 80 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@ class LibraryTreeLoader(
4848
val startIndex: Int? = null
4949
)
5050

51+
/** Configuration for creating a folder MediaItem. */
52+
private data class MediaItemConfig(
53+
val id: String,
54+
val title: String,
55+
val mediaType: Int,
56+
val subtitle: String? = null,
57+
val extras: Bundle? = null,
58+
val artworkUri: android.net.Uri? = null,
59+
val isPlayable: Boolean = false,
60+
val isBrowsable: Boolean = true
61+
)
62+
5163
// --- Helpers ---
5264

5365
private fun getEnabledTabs(): List<ViewPager2Adapter.Companion.Tab> {
@@ -64,15 +76,15 @@ class LibraryTreeLoader(
6476
putInt(MediaConstants.EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM)
6577
}
6678
return when (id) {
67-
"root" -> createFolderItem("root", "", MediaMetadata.MEDIA_TYPE_FOLDER_MIXED)
68-
"more" -> createFolderItem("more", context.getString(R.string.more), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED)
69-
"songs" -> createFolderItem("songs", context.getString(R.string.category_songs), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED)
70-
"albums" -> createFolderItem("albums", context.getString(R.string.category_albums), MediaMetadata.MEDIA_TYPE_FOLDER_ALBUMS, extras = gridExtras)
71-
"artists" -> createFolderItem("artists", context.getString(R.string.category_artists), MediaMetadata.MEDIA_TYPE_FOLDER_ARTISTS, extras = gridExtras)
72-
"genres" -> createFolderItem("genres", context.getString(R.string.category_genres), MediaMetadata.MEDIA_TYPE_FOLDER_GENRES)
73-
"dates" -> createFolderItem("dates", context.getString(R.string.category_dates), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED)
74-
"folders" -> createFolderItem("folders", context.getString(R.string.folders), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED)
75-
"playlists" -> createFolderItem("playlists", context.getString(R.string.category_playlists), MediaMetadata.MEDIA_TYPE_FOLDER_PLAYLISTS)
79+
"root" -> createFolderItem(MediaItemConfig("root", "", MediaMetadata.MEDIA_TYPE_FOLDER_MIXED))
80+
"more" -> createFolderItem(MediaItemConfig("more", context.getString(R.string.more), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED))
81+
"songs" -> createFolderItem(MediaItemConfig("songs", context.getString(R.string.category_songs), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED))
82+
"albums" -> createFolderItem(MediaItemConfig("albums", context.getString(R.string.category_albums), MediaMetadata.MEDIA_TYPE_FOLDER_ALBUMS, extras = gridExtras))
83+
"artists" -> createFolderItem(MediaItemConfig("artists", context.getString(R.string.category_artists), MediaMetadata.MEDIA_TYPE_FOLDER_ARTISTS, extras = gridExtras))
84+
"genres" -> createFolderItem(MediaItemConfig("genres", context.getString(R.string.category_genres), MediaMetadata.MEDIA_TYPE_FOLDER_GENRES))
85+
"dates" -> createFolderItem(MediaItemConfig("dates", context.getString(R.string.category_dates), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED))
86+
"folders" -> createFolderItem(MediaItemConfig("folders", context.getString(R.string.folders), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED))
87+
"playlists" -> createFolderItem(MediaItemConfig("playlists", context.getString(R.string.category_playlists), MediaMetadata.MEDIA_TYPE_FOLDER_PLAYLISTS))
7688
else -> null
7789
}
7890
}
@@ -90,15 +102,27 @@ class LibraryTreeLoader(
90102
}
91103

92104
private fun mapAlbumToMediaItem(item: Album): MediaItem = createFolderItem(
93-
"album_${item.id}", item.title ?: "", MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
94-
subtitle = item.albumArtist ?: item.songList.firstOrNull()?.mediaMetadata?.artist?.toString(),
95-
artworkUri = item.cover, isPlayable = true, isBrowsable = false
105+
MediaItemConfig(
106+
id = "album_${item.id}",
107+
title = item.title ?: "",
108+
mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
109+
subtitle = item.albumArtist ?: item.songList.firstOrNull()?.mediaMetadata?.artist?.toString(),
110+
artworkUri = item.cover,
111+
isPlayable = true,
112+
isBrowsable = false
113+
)
96114
)
97115

98116
private fun mapArtistToMediaItem(item: Artist): MediaItem = createFolderItem(
99-
"artist_${item.title}", item.title ?: "", MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
100-
subtitle = context.resources.getQuantityString(R.plurals.songs, item.songList.size, item.songList.size),
101-
artworkUri = item.albumList.firstOrNull()?.cover, isPlayable = true, isBrowsable = false
117+
MediaItemConfig(
118+
id = "artist_${item.title}",
119+
title = item.title ?: "",
120+
mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
121+
subtitle = context.resources.getQuantityString(R.plurals.songs, item.songList.size, item.songList.size),
122+
artworkUri = item.albumList.firstOrNull()?.cover,
123+
isPlayable = true,
124+
isBrowsable = false
125+
)
102126
)
103127

104128
private fun mapPlaylistToMediaItem(item: Playlist): MediaItem {
@@ -117,25 +141,42 @@ class LibraryTreeLoader(
117141
is uk.akane.libphonograph.dynamicitem.Favorite -> "playlist_favorite"
118142
else -> "playlist_${item.id}"
119143
}
120-
return createFolderItem(id, title, MediaMetadata.MEDIA_TYPE_FOLDER_MIXED, artworkUri = icon, isPlayable = true, isBrowsable = false)
144+
return createFolderItem(MediaItemConfig(id, title, MediaMetadata.MEDIA_TYPE_FOLDER_MIXED, artworkUri = icon, isPlayable = true, isBrowsable = false))
121145
}
122146

123147
private fun mapGenreToMediaItem(item: Genre): MediaItem = createFolderItem(
124-
"genre_${item.id}", item.title ?: context.getString(R.string.unknown_genre), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
125-
subtitle = context.resources.getQuantityString(R.plurals.songs, item.songList.size, item.songList.size),
126-
isPlayable = true, isBrowsable = false, artworkUri = null
148+
MediaItemConfig(
149+
id = "genre_${item.id}",
150+
title = item.title ?: context.getString(R.string.unknown_genre),
151+
mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
152+
subtitle = context.resources.getQuantityString(R.plurals.songs, item.songList.size, item.songList.size),
153+
isPlayable = true,
154+
isBrowsable = false,
155+
artworkUri = null
156+
)
127157
)
128158

129159
private fun mapDateToMediaItem(item: Date): MediaItem = createFolderItem(
130-
"date_${item.id}", item.title ?: context.getString(R.string.unknown_year), MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
131-
subtitle = context.resources.getQuantityString(R.plurals.songs, item.songList.size, item.songList.size),
132-
isPlayable = true, isBrowsable = false, artworkUri = null
160+
MediaItemConfig(
161+
id = "date_${item.id}",
162+
title = item.title ?: context.getString(R.string.unknown_year),
163+
mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
164+
subtitle = context.resources.getQuantityString(R.plurals.songs, item.songList.size, item.songList.size),
165+
isPlayable = true,
166+
isBrowsable = false,
167+
artworkUri = null
168+
)
133169
)
134170

135171
private fun mapFileNodeToMediaItem(item: FileNode): MediaItem = createFolderItem(
136-
"folder_${item.folderName}", item.folderName, MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
137-
subtitle = context.resources.getQuantityString(R.plurals.items, item.folderList.size + item.songList.size, item.folderList.size + item.songList.size),
138-
isPlayable = true, isBrowsable = false
172+
MediaItemConfig(
173+
id = "folder_${item.folderName}",
174+
title = item.folderName,
175+
mediaType = MediaMetadata.MEDIA_TYPE_FOLDER_MIXED,
176+
subtitle = context.resources.getQuantityString(R.plurals.items, item.folderList.size + item.songList.size, item.folderList.size + item.songList.size),
177+
isPlayable = true,
178+
isBrowsable = false
179+
)
139180
)
140181

141182
private suspend fun getSongsInParent(parentId: String): List<MediaItem> {
@@ -303,17 +344,21 @@ class LibraryTreeLoader(
303344
else -> app.reader.songListFlow.first().find { it.mediaId == mediaId }
304345
}
305346

306-
private fun createFolderItem(
307-
id: String, title: String, mediaType: Int, subtitle: String? = null,
308-
extras: Bundle? = null, artworkUri: android.net.Uri? = null,
309-
isPlayable: Boolean = false, isBrowsable: Boolean = true
310-
): MediaItem {
347+
private fun createFolderItem(config: MediaItemConfig): MediaItem {
311348
val metadataBuilder = MediaMetadata.Builder()
312-
.setTitle(title).setSubtitle(subtitle).setIsBrowsable(isBrowsable)
313-
.setIsPlayable(isPlayable).setMediaType(mediaType)
314-
if (extras != null) metadataBuilder.setExtras(extras)
315-
if (artworkUri != null) metadataBuilder.setArtworkUri(artworkUri)
316-
return MediaItem.Builder().setMediaId(id).setMediaMetadata(metadataBuilder.build()).build()
349+
.setTitle(config.title)
350+
.setSubtitle(config.subtitle)
351+
.setIsBrowsable(config.isBrowsable)
352+
.setIsPlayable(config.isPlayable)
353+
.setMediaType(config.mediaType)
354+
355+
config.extras?.let { metadataBuilder.setExtras(it) }
356+
config.artworkUri?.let { metadataBuilder.setArtworkUri(it) }
357+
358+
return MediaItem.Builder()
359+
.setMediaId(config.id)
360+
.setMediaMetadata(metadataBuilder.build())
361+
.build()
317362
}
318363

319364
fun getSearchResult(

0 commit comments

Comments
 (0)