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;
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.content.BroadcastReceiver;
import android.content.ComponentName;
@ -9,8 +15,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.IBinder;
import android.util.Log;
import android.view.SurfaceHolder;
@ -48,12 +52,32 @@ public abstract class PlaybackController {
private FeedMedia media;
private PlayerStatus status;
private ScheduledThreadPoolExecutor schedExecutor;
private static final int SCHED_EX_POOLSIZE = 1;
protected MediaPositionObserver positionObserver;
protected ScheduledFuture positionObserverFuture;
private boolean mediaInfoLoaded = false;
public PlaybackController(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) {
// ignore
}
if (positionObserver != null) {
positionObserver.cancel(true);
}
cancelPositionObserver();
}
/** Should be called in the activity's onPause() method. */
@ -146,28 +168,27 @@ public abstract class PlaybackController {
public abstract void setupGUI();
@SuppressLint("NewApi")
private void setupPositionObserver() {
if (positionObserver == null || positionObserver.isCancelled()) {
if ((positionObserverFuture != null && positionObserverFuture
.isCancelled())
|| (positionObserverFuture != null && positionObserverFuture
.isDone()) || positionObserverFuture == null) {
if (AppConfig.DEBUG)
Log.d(TAG, "Setting up position observer");
positionObserver = new MediaPositionObserver() {
@Override
protected void onProgressUpdate(Void... v) {
super.onProgressUpdate();
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());
positionObserver = new MediaPositionObserver();
positionObserverFuture = schedExecutor.scheduleWithFixedDelay(
positionObserver, MediaPositionObserver.WAITING_INTERVALL,
MediaPositionObserver.WAITING_INTERVALL,
TimeUnit.MILLISECONDS);
}
}
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);
break;
case PlaybackService.NOTIFICATION_TYPE_RELOAD:
if (positionObserver != null) {
positionObserver.cancel(true);
positionObserver = null;
}
cancelPositionObserver();
mediaInfoLoaded = false;
onReloadNotification(intent.getIntExtra(
PlaybackService.EXTRA_NOTIFICATION_CODE, -1));
@ -276,7 +294,7 @@ public abstract class PlaybackController {
/**
* 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() {
switch (status) {
@ -287,10 +305,7 @@ public abstract class PlaybackController {
case PAUSED:
postStatusMsg(R.string.player_paused_msg);
checkMediaInfoLoaded();
if (positionObserver != null) {
positionObserver.cancel(true);
positionObserver = null;
}
cancelPositionObserver();
updatePlayButtonAppearance(R.drawable.av_play);
break;
case PLAYING:
@ -372,48 +387,6 @@ public abstract class PlaybackController {
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.
*/
@ -435,10 +408,7 @@ public abstract class PlaybackController {
*/
public void onSeekBarStartTrackingTouch(SeekBar seekBar) {
// interrupt position Observer, restart later
if (positionObserver != null) {
positionObserver.cancel(true);
positionObserver = null;
}
cancelPositionObserver();
}
/**
@ -580,4 +550,24 @@ public abstract class PlaybackController {
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();
}
});
}
}
}
}