Add Room database for custom playlist
Here we go again! Doing custom playlist db
This commit is contained in:
parent
662a5eea35
commit
6ace96708b
13 changed files with 250 additions and 7 deletions
|
@ -162,7 +162,6 @@ dependencies {
|
||||||
|
|
||||||
implementation 'com.google.android.play:core:1.8.0'
|
implementation 'com.google.android.play:core:1.8.0'
|
||||||
implementation 'me.jorgecastillo:androidcolorx:0.2.0'
|
implementation 'me.jorgecastillo:androidcolorx:0.2.0'
|
||||||
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
|
|
||||||
implementation 'com.github.dhaval2404:imagepicker:1.7.1'
|
implementation 'com.github.dhaval2404:imagepicker:1.7.1'
|
||||||
|
|
||||||
def koin_version = "2.1.5"
|
def koin_version = "2.1.5"
|
||||||
|
@ -177,4 +176,9 @@ dependencies {
|
||||||
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
||||||
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
||||||
|
|
||||||
|
def room_version = "2.2.5"
|
||||||
|
implementation "androidx.room:room-runtime:$room_version"
|
||||||
|
kapt "androidx.room:room-compiler:$room_version"
|
||||||
|
implementation "androidx.room:room-ktx:$room_version"
|
||||||
|
debugImplementation 'com.amitshekhar.android:debug-db:1.0.6'
|
||||||
}
|
}
|
|
@ -20,6 +20,7 @@ import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
||||||
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
||||||
|
import com.amitshekhar.DebugDB
|
||||||
import com.anjlab.android.iab.v3.BillingProcessor
|
import com.anjlab.android.iab.v3.BillingProcessor
|
||||||
import com.anjlab.android.iab.v3.TransactionDetails
|
import com.anjlab.android.iab.v3.TransactionDetails
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
|
@ -32,7 +33,7 @@ class App : MultiDexApplication() {
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
instance = this
|
instance = this
|
||||||
|
DebugDB.getAddressLog();
|
||||||
startKoin {
|
startKoin {
|
||||||
androidContext(this@App)
|
androidContext(this@App)
|
||||||
modules(appModules)
|
modules(appModules)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package code.name.monkey.retromusic
|
package code.name.monkey.retromusic
|
||||||
|
|
||||||
|
import code.name.monkey.retromusic.db.PlaylistDatabase
|
||||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
import code.name.monkey.retromusic.fragments.albums.AlbumDetailsViewModel
|
import code.name.monkey.retromusic.fragments.albums.AlbumDetailsViewModel
|
||||||
import code.name.monkey.retromusic.fragments.artists.ArtistDetailsViewModel
|
import code.name.monkey.retromusic.fragments.artists.ArtistDetailsViewModel
|
||||||
|
@ -65,6 +66,10 @@ private val dataModule = module {
|
||||||
single {
|
single {
|
||||||
androidContext().contentResolver
|
androidContext().contentResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
PlaylistDatabase.getDatabase(get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val viewModules = module {
|
private val viewModules = module {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.view.View
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import code.name.monkey.retromusic.*
|
import code.name.monkey.retromusic.*
|
||||||
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
|
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
|
||||||
|
import code.name.monkey.retromusic.db.PlaylistDatabase
|
||||||
import code.name.monkey.retromusic.extensions.findNavController
|
import code.name.monkey.retromusic.extensions.findNavController
|
||||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote.openAndShuffleQueue
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote.openAndShuffleQueue
|
||||||
|
@ -25,6 +26,7 @@ import code.name.monkey.retromusic.util.AppRater.appLaunched
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koin.android.ext.android.get
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -55,6 +57,12 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
|
||||||
appLaunched(this)
|
appLaunched(this)
|
||||||
addMusicServiceEventListener(libraryViewModel)
|
addMusicServiceEventListener(libraryViewModel)
|
||||||
updateTabs()
|
updateTabs()
|
||||||
|
|
||||||
|
val database: PlaylistDatabase = get()
|
||||||
|
lifecycleScope.launch {
|
||||||
|
println("Size:${database.playlistDao().playlistsWithSong()}")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSupportNavigateUp(): Boolean =
|
override fun onSupportNavigateUp(): Boolean =
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package code.name.monkey.retromusic.db
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface PlaylistDao {
|
||||||
|
@Insert
|
||||||
|
suspend fun createPlaylist(playlistEntity: PlaylistEntity)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM PlaylistEntity")
|
||||||
|
suspend fun playlists(): List<PlaylistEntity>
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
@Query("SELECT * FROM PlaylistEntity")
|
||||||
|
suspend fun playlistsWithSong(): List<PlaylistWithSongs>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insertSongs(songEntities: List<SongEntity>)
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package code.name.monkey.retromusic.db
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
entities = [PlaylistEntity::class, SongEntity::class],
|
||||||
|
version = 4,
|
||||||
|
exportSchema = false
|
||||||
|
)
|
||||||
|
abstract class PlaylistDatabase : RoomDatabase() {
|
||||||
|
abstract fun playlistDao(): PlaylistDao
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
private var INSTANCE: PlaylistDatabase? = null
|
||||||
|
|
||||||
|
fun getDatabase(
|
||||||
|
context: Context
|
||||||
|
): PlaylistDatabase {
|
||||||
|
return INSTANCE ?: synchronized(this) {
|
||||||
|
val instance = Room.databaseBuilder(
|
||||||
|
context.applicationContext,
|
||||||
|
PlaylistDatabase::class.java,
|
||||||
|
"playlists.db"
|
||||||
|
).fallbackToDestructiveMigration().build()
|
||||||
|
INSTANCE = instance
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package code.name.monkey.retromusic.db
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Parcelize
|
||||||
|
class PlaylistEntity(
|
||||||
|
@PrimaryKey
|
||||||
|
@ColumnInfo(name = "playlist_name")
|
||||||
|
val playlistName: String
|
||||||
|
) : Parcelable
|
|
@ -0,0 +1,12 @@
|
||||||
|
package code.name.monkey.retromusic.db
|
||||||
|
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import androidx.room.Relation
|
||||||
|
|
||||||
|
data class PlaylistWithSongs(
|
||||||
|
@Embedded val playlistEntity: PlaylistEntity,
|
||||||
|
@Relation(
|
||||||
|
parentColumn = "playlist_name",
|
||||||
|
entityColumn = "playlist_creator_name"
|
||||||
|
) val songs: List<SongEntity>
|
||||||
|
)
|
|
@ -0,0 +1,9 @@
|
||||||
|
package code.name.monkey.retromusic.db
|
||||||
|
|
||||||
|
import androidx.annotation.WorkerThread
|
||||||
|
|
||||||
|
class RoomPlaylistRepository(private val playlistDao: PlaylistDao) {
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
suspend fun getPlaylistWithSongs(): List<PlaylistWithSongs> = playlistDao.playlistsWithSong()
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package code.name.monkey.retromusic.db
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class SongEntity(
|
||||||
|
@ColumnInfo(name = "song_id")
|
||||||
|
val songId: Int,
|
||||||
|
@ColumnInfo(name = "playlist_creator_name")
|
||||||
|
val playlistCreatorName: String
|
||||||
|
) {
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ColumnInfo(name = "song_key")
|
||||||
|
var songPrimaryKey: Long = 0
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package code.name.monkey.retromusic.dialogs
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import code.name.monkey.retromusic.R
|
||||||
|
import code.name.monkey.retromusic.db.PlaylistDatabase
|
||||||
|
import code.name.monkey.retromusic.db.PlaylistEntity
|
||||||
|
import code.name.monkey.retromusic.db.SongEntity
|
||||||
|
import code.name.monkey.retromusic.extensions.colorButtons
|
||||||
|
import code.name.monkey.retromusic.extensions.extraNotNull
|
||||||
|
import code.name.monkey.retromusic.extensions.materialDialog
|
||||||
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
import code.name.monkey.retromusic.repository.RealSongRepository
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koin.android.ext.android.get
|
||||||
|
|
||||||
|
class AddToRetroPlaylist : DialogFragment() {
|
||||||
|
companion object {
|
||||||
|
fun getInstance(playlistName: List<PlaylistEntity>): AddToRetroPlaylist {
|
||||||
|
return AddToRetroPlaylist().apply {
|
||||||
|
arguments = bundleOf("playlist_names" to playlistName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
val playlistEntities = extraNotNull<List<PlaylistEntity>>("playlist_names").value
|
||||||
|
val playlistNames = mutableListOf<String>()
|
||||||
|
playlistNames.add(requireContext().resources.getString(R.string.action_new_playlist))
|
||||||
|
for (p in playlistEntities) {
|
||||||
|
playlistNames.add(p.playlistName)
|
||||||
|
}
|
||||||
|
return materialDialog(R.string.add_playlist_title)
|
||||||
|
.setItems(playlistNames.toTypedArray()) { _, which ->
|
||||||
|
val songs = RealSongRepository(requireContext()).songs()
|
||||||
|
println(songs.size)
|
||||||
|
if (which == 0) {
|
||||||
|
CreateRetroPlaylist().show(requireActivity().supportFragmentManager, "Dialog")
|
||||||
|
} else {
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
println(Thread.currentThread().name)
|
||||||
|
val database: PlaylistDatabase = get()
|
||||||
|
val songEntities = songs.withPlaylistIds(playlistEntities[which - 1])
|
||||||
|
database.playlistDao().insertSongs(songEntities)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
.create().colorButtons()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<Song>.withPlaylistIds(playlistEntity: PlaylistEntity): List<SongEntity> {
|
||||||
|
val songEntities = map {
|
||||||
|
SongEntity(it.id, playlistEntity.playlistName)
|
||||||
|
}
|
||||||
|
println(songEntities.size)
|
||||||
|
return songEntities
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package code.name.monkey.retromusic.dialogs
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import code.name.monkey.retromusic.R
|
||||||
|
import code.name.monkey.retromusic.db.PlaylistDatabase
|
||||||
|
import code.name.monkey.retromusic.db.PlaylistEntity
|
||||||
|
import code.name.monkey.retromusic.extensions.colorButtons
|
||||||
|
import code.name.monkey.retromusic.extensions.materialDialog
|
||||||
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import kotlinx.android.synthetic.main.dialog_playlist.view.*
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koin.android.ext.android.get
|
||||||
|
|
||||||
|
class CreateRetroPlaylist : DialogFragment() {
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
val view = LayoutInflater.from(requireActivity()).inflate(R.layout.dialog_playlist, null)
|
||||||
|
val playlistView: TextInputEditText = view.actionNewPlaylist
|
||||||
|
val playlistContainer: TextInputLayout = view.actionNewPlaylistContainer
|
||||||
|
return materialDialog(R.string.new_playlist_title)
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton(
|
||||||
|
R.string.create_action
|
||||||
|
) { _, _ ->
|
||||||
|
val playlistName = playlistView.text.toString()
|
||||||
|
if (!TextUtils.isEmpty(playlistName)) {
|
||||||
|
val database: PlaylistDatabase = get()
|
||||||
|
lifecycleScope.launch {
|
||||||
|
database.playlistDao().createPlaylist(PlaylistEntity(playlistName))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
playlistContainer.error = "Playlist is can't be empty"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.create()
|
||||||
|
.colorButtons()
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,15 +4,20 @@ import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.ui.NavigationUI
|
import androidx.navigation.ui.NavigationUI
|
||||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
|
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
|
||||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
|
import code.name.monkey.retromusic.db.PlaylistDatabase
|
||||||
|
import code.name.monkey.retromusic.dialogs.AddToRetroPlaylist
|
||||||
import code.name.monkey.retromusic.extensions.findNavController
|
import code.name.monkey.retromusic.extensions.findNavController
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
import kotlinx.android.synthetic.main.fragment_library.*
|
import kotlinx.android.synthetic.main.fragment_library.*
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koin.android.ext.android.get
|
||||||
|
|
||||||
class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
|
class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
|
||||||
|
|
||||||
|
@ -55,11 +60,19 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_settings -> findNavController().navigate(
|
R.id.action_settings ->
|
||||||
|
//CreateRetroPlaylist().show(childFragmentManager, "Dialog")
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val database = get<PlaylistDatabase>()
|
||||||
|
AddToRetroPlaylist.getInstance(database.playlistDao().playlists())
|
||||||
|
.show(childFragmentManager, "PlaylistDialog")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*findNavController().navigate(
|
||||||
R.id.settingsActivity,
|
R.id.settingsActivity,
|
||||||
null,
|
null,
|
||||||
navOptions
|
navOptions
|
||||||
)
|
)*/
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue