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");
|
||||
}
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
mediaPlayerService.play(currentPlayingIndex, autoPlayStart);
|
||||
|
@ -129,7 +116,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
|||
{
|
||||
if (localMediaPlayer.currentPlaying.isCompleteFileAvailable())
|
||||
{
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
localMediaPlayer.doPlay(localMediaPlayer.currentPlaying, currentPlayingPosition, autoPlay);
|
||||
|
@ -145,7 +132,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
|||
@Override
|
||||
public synchronized void play(final int index)
|
||||
{
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context,new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
mediaPlayerService.play(index, true);
|
||||
|
@ -155,7 +142,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
|||
|
||||
public synchronized void play()
|
||||
{
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
mediaPlayerService.play();
|
||||
|
@ -167,7 +154,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
|||
public synchronized void togglePlayPause()
|
||||
{
|
||||
if (localMediaPlayer.playerState == PlayerState.IDLE) autoPlayStart = true;
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context,new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
mediaPlayerService.togglePlayPause();
|
||||
|
@ -178,7 +165,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
|||
@Override
|
||||
public synchronized void seekTo(final int position)
|
||||
{
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
mediaPlayerService.seekTo(position);
|
||||
|
@ -189,7 +176,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
|||
@Override
|
||||
public synchronized void pause()
|
||||
{
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
mediaPlayerService.pause();
|
||||
|
@ -200,7 +187,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
|||
@Override
|
||||
public synchronized void start()
|
||||
{
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
mediaPlayerService.start();
|
||||
|
@ -211,7 +198,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController
|
|||
@Override
|
||||
public synchronized void stop()
|
||||
{
|
||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, new Consumer<MediaPlayerService>() {
|
||||
@Override
|
||||
public void accept(MediaPlayerService mediaPlayerService) {
|
||||
mediaPlayerService.stop();
|
||||
|
|
|
@ -55,6 +55,7 @@ public class MediaPlayerService extends Service
|
|||
private static final int NOTIFICATION_ID = 3033;
|
||||
|
||||
private static MediaPlayerService instance = null;
|
||||
private static final Object instanceLock = new Object();
|
||||
|
||||
private final IBinder binder = new SimpleServiceBinder<>(this);
|
||||
private final Scrobbler scrobbler = new Scrobbler();
|
||||
|
@ -75,28 +76,42 @@ public class MediaPlayerService extends Service
|
|||
|
||||
public static MediaPlayerService getInstance(Context context)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (instance != null) return instance;
|
||||
synchronized (instanceLock) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (instance != null) return instance;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
{
|
||||
context.startForegroundService(new Intent(context, MediaPlayerService.class));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.startService(new Intent(context, MediaPlayerService.class));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(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()
|
||||
{
|
||||
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
|
||||
|
@ -169,19 +184,25 @@ public class MediaPlayerService extends Service
|
|||
|
||||
instance = null;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
localMediaPlayer.onDestroy();
|
||||
shufflePlayBuffer.onDestroy();
|
||||
downloader.onDestroy();
|
||||
}
|
||||
catch (Throwable ignored)
|
||||
{
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (jukeboxMediaPlayer.getValue().isEnabled())
|
||||
|
@ -252,8 +273,8 @@ public class MediaPlayerService extends Service
|
|||
|
||||
if (currentPlaying != null)
|
||||
{
|
||||
updateNotification(localMediaPlayer.playerState, currentPlaying);
|
||||
if (tabInstance != null) {
|
||||
updateNotification(localMediaPlayer.playerState, currentPlaying);
|
||||
tabInstance.showNowPlaying();
|
||||
}
|
||||
}
|
||||
|
@ -262,11 +283,11 @@ public class MediaPlayerService extends Service
|
|||
if (tabInstance != null)
|
||||
{
|
||||
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 (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
|
||||
if (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED)
|
||||
updateNotification(playerState, currentPlaying);
|
||||
if (tabInstance != null)
|
||||
{
|
||||
updateNotification(playerState, currentPlaying);
|
||||
tabInstance.showNowPlaying();
|
||||
}
|
||||
}
|
||||
|
@ -471,12 +492,12 @@ public class MediaPlayerService extends Service
|
|||
{
|
||||
if (tabInstance != null)
|
||||
{
|
||||
stopForeground(true);
|
||||
localMediaPlayer.clearRemoteControl();
|
||||
isInForeground = false;
|
||||
tabInstance.hideNowPlaying();
|
||||
stopSelf();
|
||||
}
|
||||
stopForeground(true);
|
||||
localMediaPlayer.clearRemoteControl();
|
||||
isInForeground = false;
|
||||
stopIfIdle();
|
||||
}
|
||||
|
||||
if (playerState == STARTED)
|
||||
|
|
Loading…
Reference in New Issue