1+ package com.musiclibrary.tracks
2+
3+ import android.content.ContentResolver
4+ import android.provider.MediaStore
5+ import com.musiclibrary.models.*
6+
7+ object GetTracksByArtistQuery {
8+ fun getTracksByArtist (
9+ contentResolver : ContentResolver ,
10+ artistId : String ,
11+ options : AssetsOptions ,
12+ ): PaginatedResult <Track > {
13+ val projection = arrayOf(
14+ MediaStore .Audio .Media ._ID ,
15+ MediaStore .Audio .Media .TITLE ,
16+ MediaStore .Audio .Media .ARTIST ,
17+ MediaStore .Audio .Media .ALBUM ,
18+ MediaStore .Audio .Media .DURATION ,
19+ MediaStore .Audio .Media .DATA ,
20+ MediaStore .Audio .Media .DATE_ADDED ,
21+ MediaStore .Audio .Media .SIZE ,
22+ MediaStore .Audio .Media .TRACK ,
23+ )
24+
25+ val selection = " ${MediaStore .Audio .Media .ARTIST_ID } = ? AND ${MediaStore .Audio .Media .IS_MUSIC } = 1 AND ${MediaStore .Audio .Media .DURATION } > 0"
26+ val selectionArgs = arrayOf(artistId)
27+ val sortOrder = " ${MediaStore .Audio .Media .ALBUM } ASC, ${MediaStore .Audio .Media .TRACK } ASC, ${MediaStore .Audio .Media .TITLE } ASC"
28+
29+ val cursor = contentResolver.query(
30+ MediaStore .Audio .Media .EXTERNAL_CONTENT_URI ,
31+ projection,
32+ selection,
33+ selectionArgs,
34+ sortOrder
35+ ) ? : throw RuntimeException (" Failed to query MediaStore: cursor is null" )
36+
37+ val tracks = mutableListOf<Track >()
38+ var hasNextPage: Boolean
39+ var endCursor: String? = null
40+ val totalCount = cursor.count
41+
42+ cursor.use { c ->
43+ val idColumn = c.getColumnIndexOrThrow(MediaStore .Audio .Media ._ID )
44+ val titleColumn = c.getColumnIndexOrThrow(MediaStore .Audio .Media .TITLE )
45+ val artistColumn = c.getColumnIndexOrThrow(MediaStore .Audio .Media .ARTIST )
46+ val albumColumn = c.getColumnIndexOrThrow(MediaStore .Audio .Media .ALBUM )
47+ val durationColumn = c.getColumnIndexOrThrow(MediaStore .Audio .Media .DURATION )
48+ val dataColumn = c.getColumnIndexOrThrow(MediaStore .Audio .Media .DATA )
49+ val dateAddedColumn = c.getColumnIndexOrThrow(MediaStore .Audio .Media .DATE_ADDED )
50+ val sizeColumn = c.getColumnIndexOrThrow(MediaStore .Audio .Media .SIZE )
51+
52+ // Jump to the specified start position
53+ val foundAfter = if (options.after == null ) {
54+ cursor.moveToFirst() // Move to the first record
55+ true
56+ } else {
57+ var found = false
58+ if (cursor.moveToFirst()) {
59+ do {
60+ val id = cursor.getLong(idColumn).toString()
61+ if (id == options.after) {
62+ found = true
63+ break
64+ }
65+ } while (cursor.moveToNext())
66+ }
67+ // Move to the next record after the specified after if found
68+ found && cursor.moveToNext()
69+ }
70+
71+ var count = 0
72+ val maxItems = options.first.coerceAtMost(1000 ) // Limit the maximum number of queries
73+
74+ while (foundAfter && count < maxItems) {
75+ try {
76+ val id = c.getLong(idColumn)
77+ val data = c.getString(dataColumn) ? : " "
78+
79+ // Skip invalid data
80+ if (data.isEmpty()) {
81+ continue
82+ }
83+
84+ val title = c.getString(titleColumn) ? : " "
85+ val artist = c.getString(artistColumn)
86+ val album = c.getString(albumColumn)
87+ val duration = c.getLong(durationColumn) / 1000.0 // Convert to seconds
88+ val dateAdded = c.getLong(dateAddedColumn)
89+ val fileSize = c.getLong(sizeColumn)
90+ val artworkUri = " content://media/external/audio/media/${id} /albumart"
91+
92+ // Create a Track
93+ val track = Track (
94+ id = id.toString(),
95+ title = title,
96+ artist = artist,
97+ artwork = artworkUri,
98+ album = album,
99+ duration = duration,
100+ url = " file://$data " ,
101+ createdAt = dateAdded * 1000 , // Convert to milliseconds
102+ modifiedAt = dateAdded * 1000 , // Convert to milliseconds
103+ fileSize = fileSize
104+ )
105+
106+ tracks.add(track)
107+ endCursor = id.toString()
108+ count++
109+ } catch (e: Exception ) {
110+ continue
111+ }
112+
113+ if (! cursor.moveToNext()) break
114+ }
115+
116+ // Check if there are more data
117+ hasNextPage = ! c.isAfterLast
118+ }
119+
120+ return PaginatedResult (
121+ items = tracks,
122+ hasNextPage = hasNextPage,
123+ endCursor = endCursor,
124+ totalCount = totalCount
125+ )
126+ }
127+ }
0 commit comments