From ecbf5fc2924bf97be6ee9e59e6efbf000486340b Mon Sep 17 00:00:00 2001 From: Karim Abou Zeid Date: Sun, 25 Jan 2015 21:36:50 +0100 Subject: [PATCH] Rewrite of shuffle function - shuffle function should work now --- .../helper/MusicPlayerRemote.java | 40 +++-- .../materialmusic/helper/ShuffleHelper.java | 21 +++ .../materialmusic/helper/Shuffler.java | 52 ------ .../kabouzeid/materialmusic/misc/AppKeys.java | 1 + .../materialmusic/service/MusicService.java | 163 +++++++++--------- .../ui/activities/AlbumDetailActivity.java | 3 +- .../ViewPagerTabArtistSongListFragment.java | 3 +- .../SongViewFragment.java | 3 +- 8 files changed, 134 insertions(+), 152 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/materialmusic/helper/ShuffleHelper.java delete mode 100644 app/src/main/java/com/kabouzeid/materialmusic/helper/Shuffler.java diff --git a/app/src/main/java/com/kabouzeid/materialmusic/helper/MusicPlayerRemote.java b/app/src/main/java/com/kabouzeid/materialmusic/helper/MusicPlayerRemote.java index 5ca44c36..35a09bbd 100644 --- a/app/src/main/java/com/kabouzeid/materialmusic/helper/MusicPlayerRemote.java +++ b/app/src/main/java/com/kabouzeid/materialmusic/helper/MusicPlayerRemote.java @@ -30,6 +30,7 @@ public class MusicPlayerRemote implements OnMusicRemoteEventListener { private int position = -1; private List playingQueue; + private List restoredOriginalQueue; private List onMusicRemoteEventListeners; private MusicService musicService; @@ -39,6 +40,7 @@ public class MusicPlayerRemote implements OnMusicRemoteEventListener { public MusicPlayerRemote(Context context) { app = (App) context.getApplicationContext(); playingQueue = new ArrayList<>(); + restoredOriginalQueue = new ArrayList<>(); onMusicRemoteEventListeners = new ArrayList<>(); startAndBindService(); } @@ -56,10 +58,9 @@ public class MusicPlayerRemote implements OnMusicRemoteEventListener { public void onServiceConnected(ComponentName name, IBinder service) { MusicService.MusicBinder binder = (MusicService.MusicBinder) service; musicService = binder.getService(); - musicService.setPosition(position); musicBound = true; + musicService.restorePreviousState(restoredOriginalQueue, playingQueue, position); musicService.addOnMusicRemoteEventListener(MusicPlayerRemote.this); - setPlayingQueue(playingQueue); notifyOnMusicRemoteEventListeners(MusicRemoteEvent.SERVICE_CONNECTED); } @@ -70,16 +71,9 @@ public class MusicPlayerRemote implements OnMusicRemoteEventListener { } }; - public boolean playSongAt(int position) { + public boolean playSongAt(final int position) { if (musicBound) { - if (position < getPlayingQueue().size() && position >= 0) { - this.position = position; - musicService.setPosition(position); - musicService.playSong(); - return true; - } else { - Log.e(TAG, "No song in queue at given index!"); - } + musicService.playSongAt(position); } return false; } @@ -139,10 +133,17 @@ public class MusicPlayerRemote implements OnMusicRemoteEventListener { return position; } - public void setPlayingQueue(List songs) { - playingQueue = songs; + private void setPosition(int position) { + this.position = position; if (musicBound) { - musicService.setPlayingQueue(playingQueue); + musicService.setPosition(position); + } + } + + public void openQueue(final List playingQueue, final int startPosition, final boolean startPlaying) { + this.playingQueue = playingQueue; + if (musicBound) { + musicService.openQueue(this.playingQueue, startPosition, startPlaying); } } @@ -254,12 +255,17 @@ public class MusicPlayerRemote implements OnMusicRemoteEventListener { public void restorePreviousState() { try { List restoredQueue = (ArrayList) InternalStorageUtil.readObject(app, AppKeys.IS_PLAYING_QUEUE); + List restoredOriginalQueue = (ArrayList) InternalStorageUtil.readObject(app, AppKeys.IS_ORIGINAL_PLAYING_QUEUE); int restoredPosition = (int) InternalStorageUtil.readObject(app, AppKeys.IS_POSITION_IN_QUEUE); - setPlayingQueue(restoredQueue); - position = restoredPosition; + if (musicBound) { - musicService.setPosition(restoredPosition); + musicService.restorePreviousState(restoredOriginalQueue, restoredQueue, restoredPosition); } + + playingQueue = restoredQueue; + this.restoredOriginalQueue = restoredOriginalQueue; + position = restoredPosition; + notifyOnMusicRemoteEventListeners(MusicRemoteEvent.STATE_RESTORED); Log.i(TAG, "restored last state"); } catch (IOException | ClassNotFoundException | ClassCastException e) { diff --git a/app/src/main/java/com/kabouzeid/materialmusic/helper/ShuffleHelper.java b/app/src/main/java/com/kabouzeid/materialmusic/helper/ShuffleHelper.java new file mode 100644 index 00000000..6fc21740 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/materialmusic/helper/ShuffleHelper.java @@ -0,0 +1,21 @@ +package com.kabouzeid.materialmusic.helper; + +import com.kabouzeid.materialmusic.model.Song; + +import java.util.Collections; +import java.util.List; + +/** + * Created by karim on 24.01.15. + */ +public class ShuffleHelper { + public static void makeShuffleList(List listToShuffle, final int current) { + if (current >= 0) { + Song song = listToShuffle.remove(current); + Collections.shuffle(listToShuffle); + listToShuffle.add(0, song); + } else { + Collections.shuffle(listToShuffle); + } + } +} diff --git a/app/src/main/java/com/kabouzeid/materialmusic/helper/Shuffler.java b/app/src/main/java/com/kabouzeid/materialmusic/helper/Shuffler.java deleted file mode 100644 index 56a5de70..00000000 --- a/app/src/main/java/com/kabouzeid/materialmusic/helper/Shuffler.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.kabouzeid.materialmusic.helper; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Created by karim on 24.01.15. - */ -public class Shuffler { - private static int MAX_HISTORY_SIZE = 250; - private List order = new ArrayList<>(); - private int position; - private int interval; - - public Shuffler(final int interval) { - order = getShuffledOrderList(interval); - this.interval = interval; - } - - public int nextInt(boolean infinite) { - position = position + 1; - if (position > order.size() - 1) { - if (infinite) { - order.addAll(getShuffledOrderList(interval)); - if (order.size() > Math.max(interval, MAX_HISTORY_SIZE)) { - order = order.subList(order.size() / 2 - 1, order.size() - 1); - } - } else { - return order.get(order.size() - 1); - } - } - return order.get(position); - } - - public int previousInt() { - position = position - 1; - if (position < 0) { - position = 0; - } - return order.get(position); - } - - private List getShuffledOrderList(int interval) { - final List newList = new ArrayList<>(); - for (int i = 0; i < interval; i++) { - newList.add(i); - } - Collections.shuffle(newList); - return newList; - } -} diff --git a/app/src/main/java/com/kabouzeid/materialmusic/misc/AppKeys.java b/app/src/main/java/com/kabouzeid/materialmusic/misc/AppKeys.java index b517cd6e..aca91f27 100644 --- a/app/src/main/java/com/kabouzeid/materialmusic/misc/AppKeys.java +++ b/app/src/main/java/com/kabouzeid/materialmusic/misc/AppKeys.java @@ -11,6 +11,7 @@ public final class AppKeys { public static final String SP_SHUFFLE_MODE = "com.kabouzeid.materialmusic.SHUFFLE_MODE"; public static final String SP_REPEAT_MODE = "com.kabouzeid.materialmusic.REPEAT_MODE"; + public static final String IS_ORIGINAL_PLAYING_QUEUE = "com.kabouzeid.materialmusic.ORIGINAL_PLAYING_QUEUE"; public static final String IS_PLAYING_QUEUE = "com.kabouzeid.materialmusic.PLAYING_QUEUE"; public static final String IS_POSITION_IN_QUEUE = "com.kabouzeid.materialmusic.POSITION_IN_QUEUE"; public static final String IS_ARTIST_JSON_INFO_CACHE = "com.kabouzeid.materialmusic.ARTIST_JSON_INFO_CACHE"; diff --git a/app/src/main/java/com/kabouzeid/materialmusic/service/MusicService.java b/app/src/main/java/com/kabouzeid/materialmusic/service/MusicService.java index f1d28b60..989ba228 100644 --- a/app/src/main/java/com/kabouzeid/materialmusic/service/MusicService.java +++ b/app/src/main/java/com/kabouzeid/materialmusic/service/MusicService.java @@ -23,7 +23,7 @@ import android.widget.Toast; import com.kabouzeid.materialmusic.R; import com.kabouzeid.materialmusic.helper.NotificationHelper; -import com.kabouzeid.materialmusic.helper.Shuffler; +import com.kabouzeid.materialmusic.helper.ShuffleHelper; import com.kabouzeid.materialmusic.interfaces.OnMusicRemoteEventListener; import com.kabouzeid.materialmusic.misc.AppKeys; import com.kabouzeid.materialmusic.model.MusicRemoteEvent; @@ -34,7 +34,6 @@ import com.nostra13.universalimageloader.core.ImageLoader; import java.io.IOException; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, AudioManager.OnAudioFocusChangeListener { @@ -57,7 +56,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe private MediaPlayer player; private List playingQueue; - private LinkedList playingHistory; + private List originalPlayingQueue; private List onMusicRemoteEventListeners; private int currentSongId = -1; private int position = -1; @@ -70,7 +69,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe private NotificationHelper notificationHelper; private AudioManager audioManager; private RemoteControlClient remoteControlClient; - private Shuffler shuffler; private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override @@ -96,7 +94,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe super.onCreate(); isPlayerPrepared = false; playingQueue = new ArrayList<>(); - playingHistory = new LinkedList<>(); + originalPlayingQueue = new ArrayList<>(); onMusicRemoteEventListeners = new ArrayList<>(); notificationHelper = new NotificationHelper(this); @@ -106,13 +104,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe registerEverything(); } - private Shuffler getShuffler() { - if (shuffler == null) { - shuffler = new Shuffler(playingQueue.size()); - } - return shuffler; - } - private boolean requestFocus() { int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); @@ -253,7 +244,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe private void killEverythingAndReleaseResources() { savePosition(); - saveQueue(); + saveQueues(); stopPlaying(); notificationHelper.killNotification(); stopSelf(); @@ -276,14 +267,29 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe notificationHelper.buildNotification(playingQueue.get(position), isPlaying()); } - public void setPlayingQueue(List songs) { - if (!playingQueue.equals(songs)) { - this.playingQueue = songs; - shuffler = new Shuffler(playingQueue.size()); - saveQueue(); + public void openQueue(final List playingQueue, final int startPosition, final boolean startPlaying) { + if (playingQueue != null && !playingQueue.isEmpty() && startPosition >= 0 && startPosition < playingQueue.size()) { + originalPlayingQueue = playingQueue; + this.playingQueue = new ArrayList<>(originalPlayingQueue); + setPosition(startPosition); + if (shuffleMode == SHUFFLE_MODE_SHUFFLE) { + ShuffleHelper.makeShuffleList(this.playingQueue, startPosition); + setPosition(0); + } + if (startPlaying) { + playSong(); + } + saveState(); } } + public void restorePreviousState(final List originalPlayingQueue, final List playingQueue, int position) { + this.originalPlayingQueue = originalPlayingQueue; + this.playingQueue = playingQueue; + this.position = position; + saveState(); + } + public List getPlayingQueue() { return playingQueue; } @@ -309,9 +315,9 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe player.setVolume(1.0f, 1.0f); if (wasPlayingBeforeFocusLoss) { resumePlaying(); - updateRemoteControlClient(getPlayingQueue().get(position)); + updateRemoteControlClient(getPlayingQueue().get(getPosition())); } - updateRemoteControlClient(getPlayingQueue().get(position)); + updateRemoteControlClient(getPlayingQueue().get(getPosition())); break; case AudioManager.AUDIOFOCUS_LOSS: @@ -344,6 +350,15 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe } } + public void playSongAt(final int position) { + if (position < getPlayingQueue().size() && position >= 0) { + setPosition(position); + playSong(); + } else { + Log.e(TAG, "No song in queue at given index!"); + } + } + public void playSong() { if (requestFocus()) { setUpMediaPlayerIfNeeded(); @@ -353,9 +368,9 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe Uri trackUri = getCurrentPositionTrackUri(); try { player.setDataSource(getApplicationContext(), trackUri); - currentSongId = playingQueue.get(position).id; + currentSongId = getPlayingQueue().get(getPosition()).id; updateNotification(); - updateRemoteControlClient(getPlayingQueue().get(position)); + updateRemoteControlClient(getPlayingQueue().get(getPosition())); player.prepareAsync(); } catch (Exception e) { Log.e("MUSIC SERVICE", "Error setting data source", e); @@ -407,7 +422,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe public void playNextSong() { if (position != -1) { if (isPlayerPrepared) { - setPosition(getNextPosition()); playSong(); notifyOnMusicRemoteEventListeners(MusicRemoteEvent.NEXT); @@ -437,29 +451,15 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe int position = 0; switch (repeatMode) { case REPEAT_MODE_NONE: - switch (shuffleMode) { - case SHUFFLE_MODE_NONE: - position = getPosition() + 1; - if (isLastTrack()) { - position -= 1; - } - break; - case SHUFFLE_MODE_SHUFFLE: - position = getShuffler().nextInt(false); - break; + position = getPosition() + 1; + if (isLastTrack()) { + position -= 1; } break; case REPEAT_MODE_ALL: - switch (shuffleMode) { - case SHUFFLE_MODE_NONE: - position = getPosition() + 1; - if (isLastTrack()) { - position = 0; - } - break; - case SHUFFLE_MODE_SHUFFLE: - position = getShuffler().nextInt(true); - break; + position = getPosition() + 1; + if (isLastTrack()) { + position = 0; } break; case REPEAT_MODE_THIS: @@ -473,29 +473,15 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe int position = 0; switch (repeatMode) { case REPEAT_MODE_NONE: - switch (shuffleMode) { - case SHUFFLE_MODE_NONE: - position = getPosition() - 1; - if (position < 0) { - position = 0; - } - break; - case SHUFFLE_MODE_SHUFFLE: - position = getShuffler().previousInt(); - break; + position = getPosition() - 1; + if (position < 0) { + position = 0; } break; case REPEAT_MODE_ALL: - switch (shuffleMode) { - case SHUFFLE_MODE_NONE: - position = getPosition() - 1; - if (position < 0) { - position = getPlayingQueue().size() - 1; - } - break; - case SHUFFLE_MODE_SHUFFLE: - position = getShuffler().previousInt(); - break; + position = getPosition() - 1; + if (position < 0) { + position = getPlayingQueue().size() - 1; } break; case REPEAT_MODE_THIS: @@ -526,10 +512,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe } public boolean isPlayerPrepared() { - if (player == null) { - return false; - } - return isPlayerPrepared; + return player != null && isPlayerPrepared; } private boolean isLastTrack() { @@ -547,13 +530,24 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe onMusicRemoteEventListeners.add(onMusicRemoteEventListener); } - public void saveQueue() { - try { - InternalStorageUtil.writeObject(MusicService.this, AppKeys.IS_PLAYING_QUEUE, getPlayingQueue()); - Log.i(TAG, "saved current queue state"); - } catch (IOException e) { - Log.e(TAG, "error while saving music service queue state", e); - } + public void saveState() { + saveQueues(); + savePosition(); + } + + public void saveQueues() { + new Thread(new Runnable() { + @Override + public void run() { + try { + InternalStorageUtil.writeObject(MusicService.this, AppKeys.IS_PLAYING_QUEUE, playingQueue); + InternalStorageUtil.writeObject(MusicService.this, AppKeys.IS_ORIGINAL_PLAYING_QUEUE, originalPlayingQueue); + Log.i(TAG, "saved current queue state"); + } catch (IOException e) { + Log.e(TAG, "error while saving music service queue state", e); + } + } + }).start(); } public void savePosition() { @@ -573,12 +567,27 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe public void setShuffleMode(final int shuffleMode) { switch (shuffleMode) { case SHUFFLE_MODE_SHUFFLE: - shuffler = new Shuffler(getPlayingQueue().size()); + this.shuffleMode = shuffleMode; + PreferenceManager.getDefaultSharedPreferences(this).edit() + .putInt(AppKeys.SP_SHUFFLE_MODE, shuffleMode) + .apply(); + ShuffleHelper.makeShuffleList(this.playingQueue, getPosition()); + setPosition(0); + notifyOnMusicRemoteEventListeners(MusicRemoteEvent.SHUFFLE_MODE_CHANGED); + break; case SHUFFLE_MODE_NONE: this.shuffleMode = shuffleMode; PreferenceManager.getDefaultSharedPreferences(this).edit() .putInt(AppKeys.SP_SHUFFLE_MODE, shuffleMode) .apply(); + playingQueue = new ArrayList<>(originalPlayingQueue); + int newPosition = 0; + for (Song song : playingQueue) { + if (song.id == currentSongId) { + newPosition = playingQueue.indexOf(song); + } + } + setPosition(newPosition); notifyOnMusicRemoteEventListeners(MusicRemoteEvent.SHUFFLE_MODE_CHANGED); break; } @@ -599,7 +608,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe } public void cycleRepeatMode() { - switch (repeatMode) { + switch (getRepeatMode()) { case REPEAT_MODE_NONE: setRepeatMode(REPEAT_MODE_ALL); break; @@ -613,7 +622,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe } public void toggleShuffle() { - if (shuffleMode == SHUFFLE_MODE_NONE) { + if (getShuffleMode() == SHUFFLE_MODE_NONE) { setShuffleMode(SHUFFLE_MODE_SHUFFLE); } else { setShuffleMode(SHUFFLE_MODE_NONE); diff --git a/app/src/main/java/com/kabouzeid/materialmusic/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/materialmusic/ui/activities/AlbumDetailActivity.java index 6fd41021..5c6e2c26 100644 --- a/app/src/main/java/com/kabouzeid/materialmusic/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/materialmusic/ui/activities/AlbumDetailActivity.java @@ -236,8 +236,7 @@ public class AlbumDetailActivity extends AbsFabActivity implements OnMusicRemote @Override public void onItemClick(AdapterView parent, View view, int position, long id) { if (position > 0) { - app.getMusicPlayerRemote().setPlayingQueue(songs); - app.getMusicPlayerRemote().playSongAt(position - 1); + app.getMusicPlayerRemote().openQueue(songs, position - 1, true); } } }); diff --git a/app/src/main/java/com/kabouzeid/materialmusic/ui/fragments/artistviewpager/ViewPagerTabArtistSongListFragment.java b/app/src/main/java/com/kabouzeid/materialmusic/ui/fragments/artistviewpager/ViewPagerTabArtistSongListFragment.java index ab732b32..4d299446 100644 --- a/app/src/main/java/com/kabouzeid/materialmusic/ui/fragments/artistviewpager/ViewPagerTabArtistSongListFragment.java +++ b/app/src/main/java/com/kabouzeid/materialmusic/ui/fragments/artistviewpager/ViewPagerTabArtistSongListFragment.java @@ -29,8 +29,7 @@ public class ViewPagerTabArtistSongListFragment extends AbsViewPagerTabArtistLis setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - app.getMusicPlayerRemote().setPlayingQueue(songs); - app.getMusicPlayerRemote().playSongAt(position); + app.getMusicPlayerRemote().openQueue(songs, position, true); } }); return adapter; diff --git a/app/src/main/java/com/kabouzeid/materialmusic/ui/fragments/mainactivityfragments/SongViewFragment.java b/app/src/main/java/com/kabouzeid/materialmusic/ui/fragments/mainactivityfragments/SongViewFragment.java index 3d48ccd5..5e454694 100644 --- a/app/src/main/java/com/kabouzeid/materialmusic/ui/fragments/mainactivityfragments/SongViewFragment.java +++ b/app/src/main/java/com/kabouzeid/materialmusic/ui/fragments/mainactivityfragments/SongViewFragment.java @@ -82,8 +82,7 @@ public class SongViewFragment extends Fragment implements KabSearchAbleFragment absListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - app.getMusicPlayerRemote().setPlayingQueue(songs); - app.getMusicPlayerRemote().playSongAt(position); + app.getMusicPlayerRemote().openQueue(songs, position, true); } });