package de.danoeh.antennapodsp.asynctask;
import android.app.Activity;
import android.content.*;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import de.danoeh.antennapodsp.AppConfig;
import de.danoeh.antennapodsp.service.download.DownloadService;
import de.danoeh.antennapodsp.service.download.Downloader;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Provides access to the DownloadService's list of items that are currently being downloaded.
* The DownloadObserver object should be created in the activity's onCreate() method. resume() and pause()
* should be called in the activity's onResume() and onPause() methods
*/
public class DownloadObserver {
private static final String TAG = "DownloadObserver";
/**
* Time period between update notifications.
*/
public static final int WAITING_INTERVAL_MS = 1000;
private volatile Activity activity;
private final Handler handler;
private final Callback callback;
private DownloadService downloadService = null;
private AtomicBoolean mIsBound = new AtomicBoolean(false);
private Thread refresherThread;
private AtomicBoolean refresherThreadRunning = new AtomicBoolean(false);
/**
* Creates a new download observer.
*
* @param activity Used for registering receivers
* @param handler All callback methods are executed on this handler. The handler MUST run on the GUI thread.
* @param callback Callback methods for posting content updates
* @throws java.lang.IllegalArgumentException if one of the arguments is null.
*/
public DownloadObserver(Activity activity, Handler handler, Callback callback) {
if (activity == null) throw new IllegalArgumentException("activity = null");
if (handler == null) throw new IllegalArgumentException("handler = null");
if (callback == null) throw new IllegalArgumentException("callback = null");
this.activity = activity;
this.handler = handler;
this.callback = callback;
}
public void onResume() {
if (AppConfig.DEBUG) Log.d(TAG, "DownloadObserver resumed");
activity.registerReceiver(contentChangedReceiver, new IntentFilter(DownloadService.ACTION_DOWNLOADS_CONTENT_CHANGED));
connectToDownloadService();
}
public void onPause() {
if (AppConfig.DEBUG) Log.d(TAG, "DownloadObserver paused");
try {
activity.unregisterReceiver(contentChangedReceiver);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
activity.unbindService(mConnection);
stopRefresher();
}
private BroadcastReceiver contentChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// reconnect to DownloadService if connection has been closed
if (downloadService == null) {
connectToDownloadService();
}
callback.onContentChanged();
startRefresher();
}
};
public interface Callback {
void onContentChanged();
void onDownloadDataAvailable(List<Downloader> downloaderList);
}
private void connectToDownloadService() {
activity.bindService(new Intent(activity, DownloadService.class), mConnection, 0);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName className) {
downloadService = null;
mIsBound.set(false);
stopRefresher();
Log.i(TAG, "Closed connection with DownloadService.");
}
public void onServiceConnected(ComponentName name, IBinder service) {
downloadService = ((DownloadService.LocalBinder) service)
.getService();
mIsBound.set(true);
if (AppConfig.DEBUG)
Log.d(TAG, "Connection to service established");
List<Downloader> downloaderList = downloadService.getDownloads();
if (downloaderList != null && !downloaderList.isEmpty()) {
callback.onDownloadDataAvailable(downloaderList);
startRefresher();
}
}
};
private void stopRefresher() {
if (refresherThread != null) {
refresherThread.interrupt();
}
}
private void startRefresher() {
if (refresherThread == null || refresherThread.isInterrupted()) {
refresherThread = new Thread(new RefresherThread());
refresherThread.start();
}
}
private class RefresherThread implements Runnable {
public void run() {
refresherThreadRunning.set(true);
while (!Thread.interrupted()) {
try {
Thread.sleep(WAITING_INTERVAL_MS);
} catch (InterruptedException e) {
Log.d(TAG, "Refresher thread was interrupted");
}
if (mIsBound.get()) {
postUpdate();
}
}
refresherThreadRunning.set(false);
}
private void postUpdate() {
handler.post(new Runnable() {
@Override
public void run() {
callback.onContentChanged();
if (downloadService != null) {
List<Downloader> downloaderList = downloadService.getDownloads();
if (downloaderList == null || downloaderList.isEmpty()) {
Thread.currentThread().interrupt();
}
}
}
});
}
}
public void setActivity(Activity activity) {
if (activity == null) throw new IllegalArgumentException("activity = null");
this.activity = activity;
}
}