From 2da9d1c5b7a54f88e5fb62c9697bfd5b1d589efa Mon Sep 17 00:00:00 2001 From: h4h13 Date: Sat, 25 Apr 2020 12:57:05 +0530 Subject: [PATCH] Added room for now playing queue --- app/build.gradle | 5 +++ .../activities/PlayingQueueActivity.kt | 2 +- .../adapter/album/AlbumCoverPagerAdapter.kt | 6 +-- .../adapter/song/PlayingQueueAdapter.kt | 7 ++-- .../fragments/base/AbsPlayerFragment.kt | 2 +- .../mainactivity/PlayingQueueFragment.kt | 2 +- .../retromusic/helper/MusicPlayerRemote.kt | 12 ++++-- .../code/name/monkey/retromusic/model/Song.kt | 18 ++++++++ .../room/MusicPlaybackQueueStoreDatabase.kt | 34 +++++++++++++++ .../retromusic/room/MusicQueueRepository.kt | 16 +++++++ .../monkey/retromusic/room/NowPlayingQueue.kt | 42 +++++++++++++++++++ .../name/monkey/retromusic/room/QueueDao.kt | 23 ++++++++++ .../name/monkey/retromusic/room/SongEntity.kt | 41 ++++++++++++++++++ .../retromusic/service/MusicService.java | 26 +++++++----- 14 files changed, 211 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/code/name/monkey/retromusic/room/MusicPlaybackQueueStoreDatabase.kt create mode 100644 app/src/main/java/code/name/monkey/retromusic/room/MusicQueueRepository.kt create mode 100644 app/src/main/java/code/name/monkey/retromusic/room/NowPlayingQueue.kt create mode 100644 app/src/main/java/code/name/monkey/retromusic/room/QueueDao.kt create mode 100644 app/src/main/java/code/name/monkey/retromusic/room/SongEntity.kt diff --git a/app/build.gradle b/app/build.gradle index 39eba04b..c3022ad0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -184,4 +184,9 @@ dependencies { def dagger_version = "2.23.1" implementation "com.google.dagger:dagger:$dagger_version" kapt "com.google.dagger:dagger-compiler:$dagger_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" } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt index d68e2b96..0db47dbf 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/PlayingQueueActivity.kt @@ -76,7 +76,7 @@ open class PlayingQueueActivity : AbsMusicServiceActivity() { playingQueueAdapter = PlayingQueueAdapter( this, - MusicPlayerRemote.playingQueue, + MusicPlayerRemote.playingQueue.toMutableList(), MusicPlayerRemote.position, R.layout.item_queue ) diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt index 441a6588..bc3de307 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/album/AlbumCoverPagerAdapter.kt @@ -16,11 +16,10 @@ import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.PreferenceUtil import com.bumptech.glide.Glide -import java.util.* class AlbumCoverPagerAdapter( fragmentManager: FragmentManager, - private val dataSet: ArrayList + private val dataSet: List ) : CustomFragmentStatePagerAdapter(fragmentManager) { private var currentColorReceiver: AlbumCoverFragment.ColorReceiver? = null @@ -95,7 +94,8 @@ class AlbumCoverPagerAdapter( savedInstanceState: Bundle? ): View? { val finalLayout = when { - PreferenceUtil.getInstance(requireContext()).carouselEffect() -> R.layout.fragment_album_carousel_cover + PreferenceUtil.getInstance(requireContext()) + .carouselEffect() -> R.layout.fragment_album_carousel_cover else -> layout } val view = inflater.inflate(finalLayout, container, false) diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/song/PlayingQueueAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/song/PlayingQueueAdapter.kt index deba43f3..7f8f8ffb 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/song/PlayingQueueAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/song/PlayingQueueAdapter.kt @@ -23,11 +23,10 @@ import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultAct import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionRemoveItem import com.h6ah4i.android.widget.advrecyclerview.swipeable.annotation.SwipeableItemResults import me.zhanghai.android.fastscroll.PopupTextProvider -import java.util.* class PlayingQueueAdapter( activity: AppCompatActivity, - dataSet: ArrayList, + dataSet: MutableList, private var current: Int, itemLayoutRes: Int ) : SongAdapter( @@ -82,8 +81,8 @@ class PlayingQueueAdapter( // We don't want to load it in this adapter } - fun swapDataSet(dataSet: ArrayList, position: Int) { - this.dataSet = dataSet + fun swapDataSet(dataSet: List, position: Int) { + this.dataSet = dataSet.toMutableList() current = position notifyDataSetChanged() } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt index c846af64..5f3ab04e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/base/AbsPlayerFragment.kt @@ -86,7 +86,7 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(), return true } R.id.action_save_playing_queue -> { - CreatePlaylistDialog.create(MusicPlayerRemote.playingQueue) + CreatePlaylistDialog.create(ArrayList(MusicPlayerRemote.playingQueue)) .show(childFragmentManager, "ADD_TO_PLAYLIST") return true } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/PlayingQueueFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/PlayingQueueFragment.kt index ef60c39b..112136ae 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/PlayingQueueFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/PlayingQueueFragment.kt @@ -79,7 +79,7 @@ class PlayingQueueFragment : override fun createAdapter(): PlayingQueueAdapter { return PlayingQueueAdapter( requireActivity() as AppCompatActivity, - MusicPlayerRemote.playingQueue, + MusicPlayerRemote.playingQueue.toMutableList(), MusicPlayerRemote.position, R.layout.item_queue ) diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt b/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt index 22f3b83a..44df3776 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt @@ -37,6 +37,7 @@ object MusicPlayerRemote { val TAG: String = MusicPlayerRemote::class.java.simpleName private val mConnectionMap = WeakHashMap() var musicService: MusicService? = null + @JvmStatic val isPlaying: Boolean get() = musicService != null && musicService!!.isPlaying @@ -64,11 +65,12 @@ object MusicPlayerRemote { musicService!!.position = position } } + @JvmStatic - val playingQueue: ArrayList + val playingQueue: List get() = if (musicService != null) { - musicService?.playingQueue as ArrayList - } else ArrayList() + musicService?.playingQueue as List + } else listOf() val songProgressMillis: Int get() = if (musicService != null) { @@ -84,6 +86,7 @@ object MusicPlayerRemote { get() = if (musicService != null) { musicService!!.repeatMode } else MusicService.REPEAT_MODE_NONE + @JvmStatic val shuffleMode: Int get() = if (musicService != null) { @@ -456,7 +459,8 @@ object MusicPlayerRemote { @TargetApi(Build.VERSION_CODES.KITKAT) private fun getSongIdFromMediaProvider(uri: Uri): String { - return DocumentsContract.getDocumentId(uri).split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1] + return DocumentsContract.getDocumentId(uri).split(":".toRegex()) + .dropLastWhile { it.isEmpty() }.toTypedArray()[1] } class ServiceBinder internal constructor(private val mCallback: ServiceConnection?) : diff --git a/app/src/main/java/code/name/monkey/retromusic/model/Song.kt b/app/src/main/java/code/name/monkey/retromusic/model/Song.kt index 9f8b33c8..765c044b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/Song.kt +++ b/app/src/main/java/code/name/monkey/retromusic/model/Song.kt @@ -14,6 +14,7 @@ package code.name.monkey.retromusic.model import android.os.Parcelable +import code.name.monkey.retromusic.room.SongEntity import kotlinx.android.parcel.Parcelize @Parcelize @@ -34,6 +35,23 @@ open class Song( companion object { + fun toSongEntity(song: Song): SongEntity { + return SongEntity( + song.id, + song.title, + song.trackNumber, + song.year, + song.duration, + song.data, + song.dateModified, + song.albumId, + song.albumName, + song.artistId, + song.artistName, + song.composer + ) + } + @JvmStatic val emptySong = Song( -1, diff --git a/app/src/main/java/code/name/monkey/retromusic/room/MusicPlaybackQueueStoreDatabase.kt b/app/src/main/java/code/name/monkey/retromusic/room/MusicPlaybackQueueStoreDatabase.kt new file mode 100644 index 00000000..f9233c7b --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/room/MusicPlaybackQueueStoreDatabase.kt @@ -0,0 +1,34 @@ +package code.name.monkey.retromusic.room + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase + +@Database(entities = [SongEntity::class], version = 2, exportSchema = false) +abstract class MusicPlaybackQueueStoreDatabase : RoomDatabase() { + + abstract fun queueDao(): QueueDao + + companion object { + @Volatile + private var INSTANCE: MusicPlaybackQueueStoreDatabase? = null + + fun getMusicDatabase(context: Context): MusicPlaybackQueueStoreDatabase { + val tempInstance = + INSTANCE + if (tempInstance != null) { + return tempInstance + } + synchronized(this) { + val instance = Room.databaseBuilder( + context.applicationContext, + MusicPlaybackQueueStoreDatabase::class.java, + "music_playback_state" + ).fallbackToDestructiveMigration().build() + INSTANCE = instance + return instance + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/room/MusicQueueRepository.kt b/app/src/main/java/code/name/monkey/retromusic/room/MusicQueueRepository.kt new file mode 100644 index 00000000..7fd99db5 --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/room/MusicQueueRepository.kt @@ -0,0 +1,16 @@ +package code.name.monkey.retromusic.room + +class MusicQueueRepository(private val queueDao: QueueDao) { + + fun getQueue(): List = queueDao.getQueue() + + fun getOriginalQueue(): List = queueDao.getQueue() + + suspend fun insertQueue(queue: List) { + queueDao.saveQueue(queue) + } + + suspend fun insertOriginalQueue(queue: List) { + queueDao.saveQueue(queue) + } +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/room/NowPlayingQueue.kt b/app/src/main/java/code/name/monkey/retromusic/room/NowPlayingQueue.kt new file mode 100644 index 00000000..f10a5963 --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/room/NowPlayingQueue.kt @@ -0,0 +1,42 @@ +package code.name.monkey.retromusic.room + +import android.content.Context +import code.name.monkey.retromusic.model.Song +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch + +class NowPlayingQueue(context: Context) { + + private val queueDao = MusicPlaybackQueueStoreDatabase.getMusicDatabase(context).queueDao() + + private val musicQueueRepository: MusicQueueRepository = MusicQueueRepository(queueDao) + + fun saveQueue(songs: List) = GlobalScope.launch(Dispatchers.IO) { + val songEntity = songs.map { + Song.toSongEntity(it) + } + musicQueueRepository.insertQueue(songEntity) + } + + fun saveOriginalQueue(playingQueue: List) = GlobalScope.launch(Dispatchers.IO) { + val songEntity = playingQueue.map { + Song.toSongEntity(it) + } + musicQueueRepository.insertOriginalQueue(songEntity) + } + + fun getQueue(): List { + val songEntity = musicQueueRepository.getQueue() + return songEntity.map { + SongEntity.toSong(it) + } + } + + fun getOriginalQueue(): List { + val songEntity = musicQueueRepository.getOriginalQueue() + return songEntity.map { + SongEntity.toSong(it) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/room/QueueDao.kt b/app/src/main/java/code/name/monkey/retromusic/room/QueueDao.kt new file mode 100644 index 00000000..ffc9bb45 --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/room/QueueDao.kt @@ -0,0 +1,23 @@ +package code.name.monkey.retromusic.room + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query + +/** + * Created by hemanths on 2020-02-23. + */ +@Dao +interface QueueDao { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun saveQueue(playingQueue: List) + + + @Query("SELECT * FROM song_entity") + fun getQueue(): List + + @Query("SELECT * FROM song_entity") + fun getOriginalQueue(): List +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/room/SongEntity.kt b/app/src/main/java/code/name/monkey/retromusic/room/SongEntity.kt new file mode 100644 index 00000000..6c65cfe9 --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/room/SongEntity.kt @@ -0,0 +1,41 @@ +package code.name.monkey.retromusic.room + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import code.name.monkey.retromusic.model.Song + +@Entity(tableName = "song_entity") +class SongEntity( + @PrimaryKey val id: Int, + @ColumnInfo(name = "title") val title: String, + @ColumnInfo(name = "track_number") val trackNumber: Int, + @ColumnInfo(name = "year") val year: Int, + @ColumnInfo(name = "duration") val duration: Long, + @ColumnInfo(name = "data") val data: String, + @ColumnInfo(name = "date_modified") val dateModified: Long, + @ColumnInfo(name = "album_id") val albumId: Int, + @ColumnInfo(name = "album_name") val albumName: String, + @ColumnInfo(name = "artist_id") val artistId: Int, + @ColumnInfo(name = "artist_name") val artistName: String, + @ColumnInfo(name = "composer") val composer: String? +) { + companion object { + fun toSong(song: SongEntity): Song { + return Song( + song.id, + song.title, + song.trackNumber, + song.year, + song.duration, + song.data, + song.dateModified, + song.albumId, + song.albumName, + song.artistId, + song.artistName, + song.composer + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java index 148ff5e7..3e566c66 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java +++ b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java @@ -74,8 +74,8 @@ import code.name.monkey.retromusic.helper.ShuffleHelper; import code.name.monkey.retromusic.model.Playlist; import code.name.monkey.retromusic.model.Song; import code.name.monkey.retromusic.providers.HistoryStore; -import code.name.monkey.retromusic.providers.MusicPlaybackQueueStore; import code.name.monkey.retromusic.providers.SongPlayCountStore; +import code.name.monkey.retromusic.room.NowPlayingQueue; import code.name.monkey.retromusic.service.notification.PlayingNotification; import code.name.monkey.retromusic.service.notification.PlayingNotificationImpl; import code.name.monkey.retromusic.service.notification.PlayingNotificationOreo; @@ -206,11 +206,9 @@ public class MusicService extends Service implements private MediaSessionCompat mediaSession; private ContentObserver mediaStoreObserver; private HandlerThread musicPlayerHandlerThread; - private boolean notHandledMetaChangedForCurrentTrack; - - private ArrayList originalPlayingQueue = new ArrayList<>(); - + private List originalPlayingQueue = new ArrayList<>(); + private List playingQueue = new ArrayList<>(); private boolean pausedByTransientLossOfFocus; private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() { @@ -239,7 +237,7 @@ public class MusicService extends Service implements updateNotification(); } }; - private ArrayList playingQueue = new ArrayList<>(); + private QueueSaveHandler queueSaveHandler; private HandlerThread queueSaveHandlerThread; private boolean queuesRestored; @@ -306,6 +304,7 @@ public class MusicService extends Service implements private ThrottledSeekHandler throttledSeekHandler; private Handler uiThreadHandler; private PowerManager.WakeLock wakeLock; + private NowPlayingQueue nowPlayingQueue; private static Bitmap copy(Bitmap bitmap) { Bitmap.Config config = bitmap.getConfig(); @@ -328,6 +327,8 @@ public class MusicService extends Service implements public void onCreate() { super.onCreate(); + nowPlayingQueue = new NowPlayingQueue(this); + final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); if (telephonyManager != null) { telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE); @@ -523,7 +524,7 @@ public class MusicService extends Service implements } @Nullable - public ArrayList getPlayingQueue() { + public List getPlayingQueue() { return playingQueue; } @@ -985,9 +986,10 @@ public class MusicService extends Service implements public synchronized void restoreQueuesAndPositionIfNecessary() { if (!queuesRestored && playingQueue.isEmpty()) { - ArrayList restoredQueue = MusicPlaybackQueueStore.getInstance(this).getSavedPlayingQueue(); - ArrayList restoredOriginalQueue = MusicPlaybackQueueStore.getInstance(this) - .getSavedOriginalPlayingQueue(); + + + List restoredQueue = nowPlayingQueue.getQueue();//MusicPlaybackQueueStore.getInstance(this).getSavedPlayingQueue(); + List restoredOriginalQueue = nowPlayingQueue.getOriginalQueue();//MusicPlaybackQueueStore.getInstance(this).getSavedOriginalPlayingQueue(); int restoredPosition = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_POSITION, -1); int restoredPositionInTrack = PreferenceManager.getDefaultSharedPreferences(this) .getInt(SAVED_POSITION_IN_TRACK, -1); @@ -1023,7 +1025,9 @@ public class MusicService extends Service implements } public void saveQueuesImpl() { - MusicPlaybackQueueStore.getInstance(this).saveQueues(playingQueue, originalPlayingQueue); + //MusicPlaybackQueueStore.getInstance(this).saveQueues(playingQueue, originalPlayingQueue); + nowPlayingQueue.saveQueue(playingQueue); + nowPlayingQueue.saveOriginalQueue(originalPlayingQueue); } public void saveState() {