Fixed concurrency problems

This commit is contained in:
Nite 2020-06-26 13:31:31 +02:00
parent b83631107c
commit 0bef3ae417
No known key found for this signature in database
GPG Key ID: 1D1AD59B1C6386C1
2 changed files with 62 additions and 54 deletions

View File

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

View File

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