Fixed concurrency problems
This commit is contained in:
parent
b83631107c
commit
0bef3ae417
|
@ -92,19 +92,6 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
Log.i(TAG, "MediaPlayerControllerImpl destroyed");
|
Log.i(TAG, "MediaPlayerControllerImpl destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeOnStartedMediaPlayerService(final Consumer<MediaPlayerService> taskToExecute)
|
|
||||||
{
|
|
||||||
Thread t = new Thread()
|
|
||||||
{
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
MediaPlayerService instance = MediaPlayerService.getInstance(context);
|
|
||||||
taskToExecute.accept(instance);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void restore(List<MusicDirectory.Entry> songs, final int currentPlayingIndex, final int currentPlayingPosition, final boolean autoPlay, boolean newPlaylist)
|
public synchronized void restore(List<MusicDirectory.Entry> songs, final int currentPlayingIndex, final int currentPlayingPosition, final boolean autoPlay, boolean newPlaylist)
|
||||||
{
|
{
|
||||||
|
@ -112,7 +99,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
|
|
||||||
if (currentPlayingIndex != -1)
|
if (currentPlayingIndex != -1)
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.play(currentPlayingIndex, autoPlayStart);
|
mediaPlayerService.play(currentPlayingIndex, autoPlayStart);
|
||||||
|
@ -129,7 +116,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
{
|
{
|
||||||
if (localMediaPlayer.currentPlaying.isCompleteFileAvailable())
|
if (localMediaPlayer.currentPlaying.isCompleteFileAvailable())
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
localMediaPlayer.doPlay(localMediaPlayer.currentPlaying, currentPlayingPosition, autoPlay);
|
localMediaPlayer.doPlay(localMediaPlayer.currentPlaying, currentPlayingPosition, autoPlay);
|
||||||
|
@ -145,7 +132,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
@Override
|
@Override
|
||||||
public synchronized void play(final int index)
|
public synchronized void play(final int index)
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context,new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.play(index, true);
|
mediaPlayerService.play(index, true);
|
||||||
|
@ -155,7 +142,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
|
|
||||||
public synchronized void play()
|
public synchronized void play()
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.play();
|
mediaPlayerService.play();
|
||||||
|
@ -167,7 +154,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
public synchronized void togglePlayPause()
|
public synchronized void togglePlayPause()
|
||||||
{
|
{
|
||||||
if (localMediaPlayer.playerState == PlayerState.IDLE) autoPlayStart = true;
|
if (localMediaPlayer.playerState == PlayerState.IDLE) autoPlayStart = true;
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context,new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.togglePlayPause();
|
mediaPlayerService.togglePlayPause();
|
||||||
|
@ -178,7 +165,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
@Override
|
@Override
|
||||||
public synchronized void seekTo(final int position)
|
public synchronized void seekTo(final int position)
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.seekTo(position);
|
mediaPlayerService.seekTo(position);
|
||||||
|
@ -189,7 +176,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
@Override
|
@Override
|
||||||
public synchronized void pause()
|
public synchronized void pause()
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.pause();
|
mediaPlayerService.pause();
|
||||||
|
@ -200,7 +187,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
@Override
|
@Override
|
||||||
public synchronized void start()
|
public synchronized void start()
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.start();
|
mediaPlayerService.start();
|
||||||
|
@ -211,7 +198,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
||||||
@Override
|
@Override
|
||||||
public synchronized void stop()
|
public synchronized void stop()
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.stop();
|
mediaPlayerService.stop();
|
||||||
|
|
|
@ -55,6 +55,7 @@ public class MediaPlayerService extends Service
|
||||||
private static final int NOTIFICATION_ID = 3033;
|
private static final int NOTIFICATION_ID = 3033;
|
||||||
|
|
||||||
private static MediaPlayerService instance = null;
|
private static MediaPlayerService instance = null;
|
||||||
|
private static final Object instanceLock = new Object();
|
||||||
|
|
||||||
private final IBinder binder = new SimpleServiceBinder<>(this);
|
private final IBinder binder = new SimpleServiceBinder<>(this);
|
||||||
private final Scrobbler scrobbler = new Scrobbler();
|
private final Scrobbler scrobbler = new Scrobbler();
|
||||||
|
@ -75,28 +76,42 @@ public class MediaPlayerService extends Service
|
||||||
|
|
||||||
public static MediaPlayerService getInstance(Context context)
|
public static MediaPlayerService getInstance(Context context)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 5; i++)
|
synchronized (instanceLock) {
|
||||||
{
|
for (int i = 0; i < 5; i++) {
|
||||||
if (instance != null) return instance;
|
if (instance != null) return instance;
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
{
|
context.startForegroundService(new Intent(context, MediaPlayerService.class));
|
||||||
context.startForegroundService(new Intent(context, MediaPlayerService.class));
|
} else {
|
||||||
}
|
context.startService(new Intent(context, MediaPlayerService.class));
|
||||||
else
|
}
|
||||||
{
|
|
||||||
context.startService(new Intent(context, MediaPlayerService.class));
|
Util.sleepQuietly(50L);
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.sleepQuietly(50L);
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaPlayerService getRunningInstance()
|
public static MediaPlayerService getRunningInstance()
|
||||||
{
|
{
|
||||||
return instance;
|
synchronized (instanceLock)
|
||||||
|
{
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void executeOnStartedMediaPlayerService(final Context context, final Consumer<MediaPlayerService> taskToExecute)
|
||||||
|
{
|
||||||
|
Thread t = new Thread()
|
||||||
|
{
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
MediaPlayerService instance = getInstance(context);
|
||||||
|
taskToExecute.accept(instance);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -169,19 +184,25 @@ public class MediaPlayerService extends Service
|
||||||
|
|
||||||
instance = null;
|
instance = null;
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
localMediaPlayer.onDestroy();
|
localMediaPlayer.onDestroy();
|
||||||
shufflePlayBuffer.onDestroy();
|
shufflePlayBuffer.onDestroy();
|
||||||
downloader.onDestroy();
|
downloader.onDestroy();
|
||||||
}
|
} catch (Throwable ignored) {
|
||||||
catch (Throwable ignored)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "MediaPlayerService stopped");
|
Log.i(TAG, "MediaPlayerService stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void stopIfIdle()
|
||||||
|
{
|
||||||
|
synchronized (instanceLock)
|
||||||
|
{
|
||||||
|
// currentPlaying could be changed from another thread in the meantime, so check again before stopping for good
|
||||||
|
if (localMediaPlayer.currentPlaying == null) stopSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void seekTo(int position)
|
public synchronized void seekTo(int position)
|
||||||
{
|
{
|
||||||
if (jukeboxMediaPlayer.getValue().isEnabled())
|
if (jukeboxMediaPlayer.getValue().isEnabled())
|
||||||
|
@ -252,8 +273,8 @@ public class MediaPlayerService extends Service
|
||||||
|
|
||||||
if (currentPlaying != null)
|
if (currentPlaying != null)
|
||||||
{
|
{
|
||||||
|
updateNotification(localMediaPlayer.playerState, currentPlaying);
|
||||||
if (tabInstance != null) {
|
if (tabInstance != null) {
|
||||||
updateNotification(localMediaPlayer.playerState, currentPlaying);
|
|
||||||
tabInstance.showNowPlaying();
|
tabInstance.showNowPlaying();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,11 +283,11 @@ public class MediaPlayerService extends Service
|
||||||
if (tabInstance != null)
|
if (tabInstance != null)
|
||||||
{
|
{
|
||||||
tabInstance.hideNowPlaying();
|
tabInstance.hideNowPlaying();
|
||||||
stopForeground(true);
|
|
||||||
localMediaPlayer.clearRemoteControl();
|
|
||||||
isInForeground = false;
|
|
||||||
stopSelf();
|
|
||||||
}
|
}
|
||||||
|
stopForeground(true);
|
||||||
|
localMediaPlayer.clearRemoteControl();
|
||||||
|
isInForeground = false;
|
||||||
|
stopIfIdle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -457,12 +478,12 @@ public class MediaPlayerService extends Service
|
||||||
|
|
||||||
if (show)
|
if (show)
|
||||||
{
|
{
|
||||||
if (tabInstance != null)
|
// Only update notification if localMediaPlayer state is one that will change the icon
|
||||||
|
if (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED)
|
||||||
{
|
{
|
||||||
// Only update notification is localMediaPlayer state is one that will change the icon
|
updateNotification(playerState, currentPlaying);
|
||||||
if (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED)
|
if (tabInstance != null)
|
||||||
{
|
{
|
||||||
updateNotification(playerState, currentPlaying);
|
|
||||||
tabInstance.showNowPlaying();
|
tabInstance.showNowPlaying();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,12 +492,12 @@ public class MediaPlayerService extends Service
|
||||||
{
|
{
|
||||||
if (tabInstance != null)
|
if (tabInstance != null)
|
||||||
{
|
{
|
||||||
stopForeground(true);
|
|
||||||
localMediaPlayer.clearRemoteControl();
|
|
||||||
isInForeground = false;
|
|
||||||
tabInstance.hideNowPlaying();
|
tabInstance.hideNowPlaying();
|
||||||
stopSelf();
|
|
||||||
}
|
}
|
||||||
|
stopForeground(true);
|
||||||
|
localMediaPlayer.clearRemoteControl();
|
||||||
|
isInForeground = false;
|
||||||
|
stopIfIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playerState == STARTED)
|
if (playerState == STARTED)
|
||||||
|
|
Loading…
Reference in New Issue