Replaced AsyncTask in PlaybackController with

ScheduledThreadPoolExecutor
This commit is contained in:
daniel oeh 2012-09-07 12:47:01 +02:00
parent 5e63586d7c
commit b24b1365b3
1 changed files with 70 additions and 80 deletions

View File

@ -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;
}
} }
/** /**
@ -580,4 +550,24 @@ public abstract class PlaybackController {
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();
}
});
}
}
}
} }