Replaced AsyncTask in PlaybackController with
ScheduledThreadPoolExecutor
This commit is contained in:
parent
5e63586d7c
commit
b24b1365b3
|
@ -1,6 +1,12 @@
|
||||||
package de.danoeh.antennapod.util;
|
package de.danoeh.antennapod.util;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import java.util.concurrent.RejectedExecutionHandler;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
|
@ -9,8 +15,6 @@ import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.media.MediaPlayer;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
|
@ -48,12 +52,32 @@ public abstract class PlaybackController {
|
||||||
private FeedMedia media;
|
private FeedMedia media;
|
||||||
private PlayerStatus status;
|
private PlayerStatus status;
|
||||||
|
|
||||||
|
private ScheduledThreadPoolExecutor schedExecutor;
|
||||||
|
private static final int SCHED_EX_POOLSIZE = 1;
|
||||||
|
|
||||||
protected MediaPositionObserver positionObserver;
|
protected MediaPositionObserver positionObserver;
|
||||||
|
protected ScheduledFuture positionObserverFuture;
|
||||||
|
|
||||||
private boolean mediaInfoLoaded = false;
|
private boolean mediaInfoLoaded = false;
|
||||||
|
|
||||||
public PlaybackController(Activity activity) {
|
public PlaybackController(Activity activity) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
|
schedExecutor = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}, new RejectedExecutionHandler() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rejectedExecution(Runnable r,
|
||||||
|
ThreadPoolExecutor executor) {
|
||||||
|
Log.w(TAG, "Rejected execution of runnable in schedExecutor");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,9 +113,7 @@ public abstract class PlaybackController {
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
if (positionObserver != null) {
|
cancelPositionObserver();
|
||||||
positionObserver.cancel(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Should be called in the activity's onPause() method. */
|
/** Should be called in the activity's onPause() method. */
|
||||||
|
@ -146,28 +168,27 @@ public abstract class PlaybackController {
|
||||||
|
|
||||||
public abstract void setupGUI();
|
public abstract void setupGUI();
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
|
||||||
private void setupPositionObserver() {
|
private void setupPositionObserver() {
|
||||||
if (positionObserver == null || positionObserver.isCancelled()) {
|
if ((positionObserverFuture != null && positionObserverFuture
|
||||||
|
.isCancelled())
|
||||||
|
|| (positionObserverFuture != null && positionObserverFuture
|
||||||
|
.isDone()) || positionObserverFuture == null) {
|
||||||
|
|
||||||
if (AppConfig.DEBUG)
|
if (AppConfig.DEBUG)
|
||||||
Log.d(TAG, "Setting up position observer");
|
Log.d(TAG, "Setting up position observer");
|
||||||
positionObserver = new MediaPositionObserver() {
|
positionObserver = new MediaPositionObserver();
|
||||||
|
positionObserverFuture = schedExecutor.scheduleWithFixedDelay(
|
||||||
@Override
|
positionObserver, MediaPositionObserver.WAITING_INTERVALL,
|
||||||
protected void onProgressUpdate(Void... v) {
|
MediaPositionObserver.WAITING_INTERVALL,
|
||||||
super.onProgressUpdate();
|
TimeUnit.MILLISECONDS);
|
||||||
onPositionObserverUpdate();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
|
||||||
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
|
|
||||||
positionObserver.executeOnExecutor(
|
|
||||||
AsyncTask.THREAD_POOL_EXECUTOR,
|
|
||||||
playbackService.getPlayer());
|
|
||||||
} else {
|
|
||||||
positionObserver.execute(playbackService.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void cancelPositionObserver() {
|
||||||
|
if (positionObserverFuture != null) {
|
||||||
|
boolean result = positionObserverFuture.cancel(true);
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, "PositionObserver cancelled. Result: " + result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,10 +252,7 @@ public abstract class PlaybackController {
|
||||||
onBufferUpdate(progress);
|
onBufferUpdate(progress);
|
||||||
break;
|
break;
|
||||||
case PlaybackService.NOTIFICATION_TYPE_RELOAD:
|
case PlaybackService.NOTIFICATION_TYPE_RELOAD:
|
||||||
if (positionObserver != null) {
|
cancelPositionObserver();
|
||||||
positionObserver.cancel(true);
|
|
||||||
positionObserver = null;
|
|
||||||
}
|
|
||||||
mediaInfoLoaded = false;
|
mediaInfoLoaded = false;
|
||||||
onReloadNotification(intent.getIntExtra(
|
onReloadNotification(intent.getIntExtra(
|
||||||
PlaybackService.EXTRA_NOTIFICATION_CODE, -1));
|
PlaybackService.EXTRA_NOTIFICATION_CODE, -1));
|
||||||
|
@ -276,7 +294,7 @@ public abstract class PlaybackController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is called whenever the PlaybackService changes it's status. This method
|
* Is called whenever the PlaybackService changes it's status. This method
|
||||||
* should be used to update the GUI or start/cancel AsyncTasks.
|
* should be used to update the GUI or start/cancel background threads.
|
||||||
*/
|
*/
|
||||||
private void handleStatus() {
|
private void handleStatus() {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
@ -287,10 +305,7 @@ public abstract class PlaybackController {
|
||||||
case PAUSED:
|
case PAUSED:
|
||||||
postStatusMsg(R.string.player_paused_msg);
|
postStatusMsg(R.string.player_paused_msg);
|
||||||
checkMediaInfoLoaded();
|
checkMediaInfoLoaded();
|
||||||
if (positionObserver != null) {
|
cancelPositionObserver();
|
||||||
positionObserver.cancel(true);
|
|
||||||
positionObserver = null;
|
|
||||||
}
|
|
||||||
updatePlayButtonAppearance(R.drawable.av_play);
|
updatePlayButtonAppearance(R.drawable.av_play);
|
||||||
break;
|
break;
|
||||||
case PLAYING:
|
case PLAYING:
|
||||||
|
@ -372,48 +387,6 @@ public abstract class PlaybackController {
|
||||||
|
|
||||||
public abstract void onServiceQueried();
|
public abstract void onServiceQueried();
|
||||||
|
|
||||||
/** Refreshes the current position of the media file that is playing. */
|
|
||||||
public class MediaPositionObserver extends
|
|
||||||
AsyncTask<MediaPlayer, Void, Void> {
|
|
||||||
|
|
||||||
private static final String TAG = "MediaPositionObserver";
|
|
||||||
private static final int WAITING_INTERVALL = 1000;
|
|
||||||
private MediaPlayer player;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCancelled() {
|
|
||||||
if (AppConfig.DEBUG)
|
|
||||||
Log.d(TAG, "Task was cancelled");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(MediaPlayer... p) {
|
|
||||||
if (AppConfig.DEBUG)
|
|
||||||
Log.d(TAG, "Background Task started");
|
|
||||||
player = p[0];
|
|
||||||
try {
|
|
||||||
while (player.isPlaying() && !isCancelled()) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(WAITING_INTERVALL);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
if (AppConfig.DEBUG)
|
|
||||||
Log.d(TAG,
|
|
||||||
"Thread was interrupted while waiting. Finishing now");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
publishProgress();
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
if (AppConfig.DEBUG)
|
|
||||||
Log.d(TAG, "player is in illegal state, exiting now");
|
|
||||||
}
|
|
||||||
if (AppConfig.DEBUG)
|
|
||||||
Log.d(TAG, "Background Task finished");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should be used by classes which implement the OnSeekBarChanged interface.
|
* Should be used by classes which implement the OnSeekBarChanged interface.
|
||||||
*/
|
*/
|
||||||
|
@ -435,10 +408,7 @@ public abstract class PlaybackController {
|
||||||
*/
|
*/
|
||||||
public void onSeekBarStartTrackingTouch(SeekBar seekBar) {
|
public void onSeekBarStartTrackingTouch(SeekBar seekBar) {
|
||||||
// interrupt position Observer, restart later
|
// interrupt position Observer, restart later
|
||||||
if (positionObserver != null) {
|
cancelPositionObserver();
|
||||||
positionObserver.cancel(true);
|
|
||||||
positionObserver = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -574,10 +544,30 @@ public abstract class PlaybackController {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyVideoSurfaceAbandoned() {
|
public void notifyVideoSurfaceAbandoned() {
|
||||||
if (playbackService != null) {
|
if (playbackService != null) {
|
||||||
playbackService.notifyVideoSurfaceAbandoned();
|
playbackService.notifyVideoSurfaceAbandoned();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Refreshes the current position of the media file that is playing. */
|
||||||
|
public class MediaPositionObserver implements Runnable {
|
||||||
|
|
||||||
|
public static final int WAITING_INTERVALL = 1000;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (playbackService != null && playbackService.getPlayer() != null
|
||||||
|
&& playbackService.getPlayer().isPlaying()) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
onPositionObserverUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue