Add Room database for custom playlist

Here we go again!

Doing custom playlist db
This commit is contained in:
Hemanth S 2020-08-20 00:13:06 +05:30
parent 662a5eea35
commit 6ace96708b
13 changed files with 250 additions and 7 deletions

View file

@ -162,7 +162,6 @@ dependencies {
implementation 'com.google.android.play:core:1.8.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'
def koin_version = "2.1.5"
@ -177,4 +176,9 @@ dependencies {
implementation "androidx.navigation:navigation-fragment-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'
}

View file

@ -20,6 +20,7 @@ import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import com.amitshekhar.DebugDB
import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.TransactionDetails
import org.koin.android.ext.koin.androidContext
@ -32,7 +33,7 @@ class App : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
instance = this
DebugDB.getAddressLog();
startKoin {
androidContext(this@App)
modules(appModules)

View file

@ -1,5 +1,6 @@
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.albums.AlbumDetailsViewModel
import code.name.monkey.retromusic.fragments.artists.ArtistDetailsViewModel
@ -65,6 +66,10 @@ private val dataModule = module {
single {
androidContext().contentResolver
}
single {
PlaylistDatabase.getDatabase(get())
}
}
private val viewModules = module {

View file

@ -10,6 +10,7 @@ import android.view.View
import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.*
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.fragments.LibraryViewModel
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 kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koin.android.ext.android.get
import org.koin.android.ext.android.inject
import java.util.*
@ -55,6 +57,12 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
appLaunched(this)
addMusicServiceEventListener(libraryViewModel)
updateTabs()
val database: PlaylistDatabase = get()
lifecycleScope.launch {
println("Size:${database.playlistDao().playlistsWithSong()}")
}
}
override fun onSupportNavigateUp(): Boolean =

View file

@ -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>)
}

View file

@ -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
}
}
}
}

View file

@ -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

View file

@ -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>
)

View file

@ -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()
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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()
}
}

View file

@ -4,15 +4,20 @@ import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.NavigationUI
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
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.fragments.base.AbsMainActivityFragment
import com.google.android.material.appbar.AppBarLayout
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) {
@ -55,11 +60,19 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_settings -> findNavController().navigate(
R.id.settingsActivity,
null,
navOptions
)
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,
null,
navOptions
)*/
}
return super.onOptionsItemSelected(item)
}