diff --git a/app/build.gradle b/app/build.gradle index 2195d43bd..3997a9ff3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { defaultConfig { applicationId "org.oxycblt.auxio" - minSdkVersion 23 + minSdkVersion 24 targetSdkVersion 30 versionCode 1 versionName "1.0" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0034403b0..e32610397 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ + + ( inflater, R.layout.fragment_library, container, false ) diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt new file mode 100644 index 000000000..dd648fef9 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt @@ -0,0 +1,14 @@ +package org.oxycblt.auxio.library + +import android.util.Log +import androidx.lifecycle.ViewModel + +class LibraryViewModel() : ViewModel() { + + // TODO: Implement music data in ViewModel + + init { + + Log.d(this::class.simpleName, "ViewModel created.") + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt new file mode 100644 index 000000000..fae291c8f --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt @@ -0,0 +1,118 @@ +package org.oxycblt.auxio.music + +import android.app.Application +import android.content.ContentResolver +import android.database.Cursor +import android.provider.MediaStore +import android.provider.MediaStore.Audio.AudioColumns +import android.util.Log + +// Storage for music data. Design largely adapted from Music Player GO: +// https://github.com/enricocid/Music-Player-GO +class MusicRepository() { + + var rawMusicList = mutableListOf() + + fun getMusic(app: Application): MutableList { + findMusic(app)?.let { rm -> + + // TODO: Sort the raw music + rawMusicList = rm + } + + return rawMusicList + } + + private fun findMusic(app: Application): MutableList? { + + try { + val musicCursor = getCursor( + app.contentResolver + ) + + // Index music files from shared storage + musicCursor?.use { cursor -> + + val nameIndex = cursor.getColumnIndexOrThrow(AudioColumns.TITLE) + val artistIndex = cursor.getColumnIndexOrThrow(AudioColumns.ARTIST) + val albumIndex = cursor.getColumnIndexOrThrow(AudioColumns.ALBUM) + val yearIndex = cursor.getColumnIndexOrThrow(AudioColumns.YEAR) + val trackIndex = cursor.getColumnIndexOrThrow(AudioColumns.TRACK) + val durationIndex = cursor.getColumnIndexOrThrow(AudioColumns.DURATION) + val idIndex = cursor.getColumnIndexOrThrow(AudioColumns._ID) + + while (cursor.moveToNext()) { + rawMusicList.add( + RawMusic( + cursor.getString(nameIndex), + cursor.getString(artistIndex), + cursor.getString(albumIndex), + cursor.getInt(yearIndex), + cursor.getInt(trackIndex), + cursor.getLong(durationIndex), + cursor.getLong(idIndex) + ) + ) + } + } + + Log.d( + this::class.simpleName, + "Music search ended with " + rawMusicList.size.toString() + " Songs found." + ) + + return rawMusicList + } catch (error: Exception) { + // TODO: Add better error handling + + Log.e(this::class.simpleName, "Something went horribly wrong.") + error.printStackTrace() + + return null + } + } + + private fun getCursor(resolver: ContentResolver): Cursor? { + Log.i(this::class.simpleName, "Getting music cursor.") + + return resolver.query( + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + arrayOf( + AudioColumns.TITLE, + AudioColumns.ARTIST, + AudioColumns.ALBUM, + AudioColumns.YEAR, + AudioColumns.TRACK, + AudioColumns.DURATION, + AudioColumns._ID + ), + AudioColumns.IS_MUSIC + "=1", null, + MediaStore.Audio.Media.DEFAULT_SORT_ORDER + ) + } + + companion object { + @Volatile + private var INSTANCE: MusicRepository? = null + + fun getInstance(): MusicRepository { + val tempInstance = INSTANCE + + if (tempInstance != null) { + return tempInstance + } + + synchronized(this) { + val newInstance = MusicRepository() + INSTANCE = newInstance + + Log.d( + MusicRepository::class.simpleName, + "Created an instance of MusicRepository." + ) + + return newInstance + } + } + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/RawMusic.kt b/app/src/main/java/org/oxycblt/auxio/music/RawMusic.kt new file mode 100644 index 000000000..5d513cf90 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/RawMusic.kt @@ -0,0 +1,13 @@ +package org.oxycblt.auxio.music + +// Class containing all relevant values for a song +// TODO: Is broken into Artist, Album, and Song classes +data class RawMusic( + val name: String?, + val artist: String?, + val album: String?, + val year: Int, + val track: Int, + val duration: Long, + val id: Long? +) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 43c1da2d3..6c34f6f2b 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,6 +1,5 @@ - diff --git a/app/src/main/res/layout/fragment_library.xml b/app/src/main/res/layout/fragment_library.xml index c013f3ca6..8be02910c 100644 --- a/app/src/main/res/layout/fragment_library.xml +++ b/app/src/main/res/layout/fragment_library.xml @@ -1,13 +1,11 @@ - + android:layout_height="match_parent"> + tools:titleTextColor="@color/primaryTextColor" /> \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml index 51f313356..f645b4c8f 100644 --- a/app/src/main/res/navigation/nav_main.xml +++ b/app/src/main/res/navigation/nav_main.xml @@ -1,6 +1,5 @@ - diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index d15919c12..9eb744fff 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -5,6 +5,5 @@ @color/primaryColor @color/primaryColor @color/primaryColor - @color/secondaryColor \ No newline at end of file