aboutsummaryrefslogtreecommitdiff
path: root/src/github/daneren2005
diff options
context:
space:
mode:
Diffstat (limited to 'src/github/daneren2005')
-rw-r--r--src/github/daneren2005/dsub/activity/SettingsActivity.java2
-rw-r--r--src/github/daneren2005/dsub/util/BackgroundTask.java156
-rw-r--r--src/github/daneren2005/dsub/util/CacheCleaner.java23
-rw-r--r--src/github/daneren2005/dsub/util/LoadingTask.java62
-rw-r--r--src/github/daneren2005/dsub/util/SilentBackgroundTask.java32
-rw-r--r--src/github/daneren2005/dsub/util/TabBackgroundTask.java48
-rw-r--r--src/github/daneren2005/dsub/view/ErrorDialog.java7
7 files changed, 195 insertions, 135 deletions
diff --git a/src/github/daneren2005/dsub/activity/SettingsActivity.java b/src/github/daneren2005/dsub/activity/SettingsActivity.java
index 40ca5570..d496a201 100644
--- a/src/github/daneren2005/dsub/activity/SettingsActivity.java
+++ b/src/github/daneren2005/dsub/activity/SettingsActivity.java
@@ -557,7 +557,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer
}
@Override
- protected void cancel() {
+ public void cancel() {
super.cancel();
Util.setActiveServer(SettingsActivity.this, previousInstance);
}
diff --git a/src/github/daneren2005/dsub/util/BackgroundTask.java b/src/github/daneren2005/dsub/util/BackgroundTask.java
index 547bbd1e..9f749116 100644
--- a/src/github/daneren2005/dsub/util/BackgroundTask.java
+++ b/src/github/daneren2005/dsub/util/BackgroundTask.java
@@ -20,10 +20,17 @@ package github.daneren2005.dsub.util;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
+import android.content.Context;
import android.os.Handler;
import android.util.Log;
import github.daneren2005.dsub.R;
@@ -33,25 +40,46 @@ import github.daneren2005.dsub.view.ErrorDialog;
* @author Sindre Mehus
*/
public abstract class BackgroundTask<T> implements ProgressListener {
-
private static final String TAG = BackgroundTask.class.getSimpleName();
- private final Activity activity;
- private final Handler handler;
- public BackgroundTask(Activity activity) {
- this.activity = activity;
- handler = new Handler();
+ private final Context context;
+ protected boolean cancelled = false;
+ protected Task task;
+
+ private static final int DEFAULT_CONCURRENCY = 5;
+ private static final Collection<Thread> threads = Collections.synchronizedCollection(new ArrayList<Thread>());
+ protected static final BlockingQueue<BackgroundTask.Task> queue = new LinkedBlockingQueue<BackgroundTask.Task>(10);
+ private static final Handler handler = new Handler();
+
+ public BackgroundTask(Context context) {
+ this.context = context;
+
+ if(threads.isEmpty()) {
+ for(int i = 0; i < DEFAULT_CONCURRENCY; i++) {
+ Thread thread = new Thread(new TaskRunnable(), String.format("BackgroundTask_%d", i));
+ threads.add(thread);
+ thread.start();
+ }
+ }
}
+ public static void stopThreads() {
+ for(Thread thread: threads) {
+ thread.interrupt();
+ }
+ threads.clear();
+ queue.clear();
+ }
+
protected Activity getActivity() {
- return activity;
+ return (context instanceof Activity) ? ((Activity) context) : null;
}
protected Handler getHandler() {
return handler;
}
- public abstract void execute();
+ public abstract void execute();
protected abstract T doInBackground() throws Throwable;
@@ -59,25 +87,28 @@ public abstract class BackgroundTask<T> implements ProgressListener {
protected void error(Throwable error) {
Log.w(TAG, "Got exception: " + error, error);
- new ErrorDialog(activity, getErrorMessage(error), true);
+ Activity activity = getActivity();
+ if(activity != null) {
+ new ErrorDialog(activity, getErrorMessage(error), true);
+ }
}
protected String getErrorMessage(Throwable error) {
- if (error instanceof IOException && !Util.isNetworkConnected(activity)) {
- return activity.getResources().getString(R.string.background_task_no_network);
+ if (error instanceof IOException && !Util.isNetworkConnected(context)) {
+ return context.getResources().getString(R.string.background_task_no_network);
}
if (error instanceof FileNotFoundException) {
- return activity.getResources().getString(R.string.background_task_not_found);
+ return context.getResources().getString(R.string.background_task_not_found);
}
if (error instanceof IOException) {
- return activity.getResources().getString(R.string.background_task_network_error);
+ return context.getResources().getString(R.string.background_task_network_error);
}
if (error instanceof XmlPullParserException) {
- return activity.getResources().getString(R.string.background_task_parse_error);
+ return context.getResources().getString(R.string.background_task_parse_error);
}
String message = error.getMessage();
@@ -87,11 +118,104 @@ public abstract class BackgroundTask<T> implements ProgressListener {
return error.getClass().getSimpleName();
}
+ public void cancel() {
+ cancelled = true;
+ if(task != null) {
+ task.cancel();
+ }
+ }
+ protected boolean isCancelled() {
+ return cancelled;
+ }
+
@Override
public abstract void updateProgress(final String message);
@Override
public void updateProgress(int messageId) {
- updateProgress(activity.getResources().getString(messageId));
+ updateProgress(context.getResources().getString(messageId));
}
-} \ No newline at end of file
+
+ protected class Task {
+ private Thread thread;
+ private AtomicBoolean taskStart = new AtomicBoolean(true);
+
+ private void execute() throws Exception {
+ if(!taskStart.get()) {
+ return;
+ }
+
+ thread = Thread.currentThread();
+ try {
+ final T result = doInBackground();
+ if(isCancelled()) {
+ return;
+ }
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ onDone(result);
+ }
+ });
+ } catch(InterruptedException interrupt) {
+ if(taskStart.get()) {
+ // Don't exit root thread if task cancelled
+ throw interrupt;
+ }
+ } catch(final Throwable t) {
+ if(isCancelled()) {
+ return;
+ }
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ onError(t);
+ } catch(Exception e) {
+ // Don't care
+ }
+ }
+ });
+ }
+ }
+
+ public void cancel() {
+ taskStart.set(false);
+ if(thread != null) {
+ thread.interrupt();
+ }
+ }
+ public void onDone(T result) {
+ done(result);
+ }
+ public void onError(Throwable t) {
+ error(t);
+ }
+ }
+
+ private class TaskRunnable implements Runnable {
+ private boolean running = true;
+
+ public TaskRunnable() {
+
+ }
+
+ @Override
+ public void run() {
+ while(running) {
+ try {
+ Task task = queue.take();
+ task.execute();
+ } catch(InterruptedException stop) {
+ running = false;
+ threads.remove(Thread.currentThread());
+ } catch(Throwable t) {
+ Log.e(TAG, "Unexpected crash in BackgroundTask thread", t);
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/github/daneren2005/dsub/util/CacheCleaner.java b/src/github/daneren2005/dsub/util/CacheCleaner.java
index 62204c76..102c1dc9 100644
--- a/src/github/daneren2005/dsub/util/CacheCleaner.java
+++ b/src/github/daneren2005/dsub/util/CacheCleaner.java
@@ -65,7 +65,7 @@ public class CacheCleaner {
}
}
- private long getMinimumDelete(List<File> files) {
+ private long getMinimumDelete(List<File> files, List<File> pinned) {
if(files.size() == 0) {
return 0L;
}
@@ -76,6 +76,9 @@ public class CacheCleaner {
for (File file : files) {
bytesUsedBySubsonic += file.length();
}
+ for (File file : pinned) {
+ bytesUsedBySubsonic += file.length();
+ }
// Ensure that file system is not more than 95% full.
StatFs stat = new StatFs(files.get(0).getPath());
@@ -118,17 +121,19 @@ public class CacheCleaner {
Log.i(TAG, "Deleted : " + Util.formatBytes(bytesDeleted));
}
- private void findCandidatesForDeletion(File file, List<File> files, List<File> dirs) {
+ private void findCandidatesForDeletion(File file, List<File> files, List<File> pinned, List<File> dirs) {
if (file.isFile()) {
String name = file.getName();
boolean isCacheFile = name.endsWith(".partial") || name.contains(".partial.") || name.endsWith(".complete") || name.contains(".complete.");
if (isCacheFile) {
files.add(file);
- }
+ } else {
+ pinned.add(file);
+ }
} else {
// Depth-first
for (File child : FileUtil.listFiles(file)) {
- findCandidatesForDeletion(child, files, dirs);
+ findCandidatesForDeletion(child, files, pinned, dirs);
}
dirs.add(file);
}
@@ -171,14 +176,15 @@ public class CacheCleaner {
try {
List<File> files = new ArrayList<File>();
+ List<File> pinned = new ArrayList<File>();
List<File> dirs = new ArrayList<File>();
- findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, dirs);
+ findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
sortByAscendingModificationTime(files);
Set<File> undeletable = findUndeletableFiles();
- deleteFiles(files, undeletable, getMinimumDelete(files), true);
+ deleteFiles(files, undeletable, getMinimumDelete(files, pinned), true);
deleteEmptyDirs(dirs, undeletable);
} catch (RuntimeException x) {
Log.e(TAG, "Error in cache cleaning.", x);
@@ -198,10 +204,11 @@ public class CacheCleaner {
try {
List<File> files = new ArrayList<File>();
+ List<File> pinned = new ArrayList<File>();
List<File> dirs = new ArrayList<File>();
- findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, dirs);
+ findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
- long bytesToDelete = getMinimumDelete(files);
+ long bytesToDelete = getMinimumDelete(files, pinned);
if(bytesToDelete > 0L) {
sortByAscendingModificationTime(files);
Set<File> undeletable = findUndeletableFiles();
diff --git a/src/github/daneren2005/dsub/util/LoadingTask.java b/src/github/daneren2005/dsub/util/LoadingTask.java
index 7faa6afe..c47931ee 100644
--- a/src/github/daneren2005/dsub/util/LoadingTask.java
+++ b/src/github/daneren2005/dsub/util/LoadingTask.java
@@ -14,9 +14,7 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> {
private final Activity tabActivity;
private ProgressDialog loading;
- private Thread thread;
private final boolean cancellable;
- private boolean cancelled = false;
public LoadingTask(Activity activity) {
super(activity);
@@ -35,56 +33,26 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> {
public void onCancel(DialogInterface dialog) {
cancel();
}
-
});
- thread = new Thread() {
- @Override
- public void run() {
- try {
- final T result = doInBackground();
- if (isCancelled()) {
- return;
- }
+ queue.offer(task = new Task() {
+ @Override
+ public void onDone(T result) {
+ loading.dismiss();
+ done(result);
+ }
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- loading.cancel();
- done(result);
- }
- });
- } catch (final Throwable t) {
- if (isCancelled()) {
- return;
- }
-
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- try {
- loading.cancel();
- error(t);
- } catch(Exception e) {
- // Don't care
- }
- }
- });
- }
- }
- };
- thread.start();
+ @Override
+ public void onError(Throwable t) {
+ loading.dismiss();
+ error(t);
+ }
+ });
}
- protected void cancel() {
- cancelled = true;
- if (thread != null) {
- thread.interrupt();
- }
- }
-
- private boolean isCancelled() {
- return (tabActivity instanceof SubsonicActivity && ((SubsonicActivity)tabActivity).isDestroyed()) || cancelled;
+ @Override
+ protected boolean isCancelled() {
+ return (tabActivity instanceof SubsonicActivity && tabActivity.isDestroyed()) || cancelled;
}
@Override
diff --git a/src/github/daneren2005/dsub/util/SilentBackgroundTask.java b/src/github/daneren2005/dsub/util/SilentBackgroundTask.java
index 7bceb467..a0db7ca4 100644
--- a/src/github/daneren2005/dsub/util/SilentBackgroundTask.java
+++ b/src/github/daneren2005/dsub/util/SilentBackgroundTask.java
@@ -18,43 +18,19 @@
*/
package github.daneren2005.dsub.util;
-import android.app.Activity;
+import android.content.Context;
/**
* @author Sindre Mehus
*/
public abstract class SilentBackgroundTask<T> extends BackgroundTask<T> {
-
- public SilentBackgroundTask(Activity activity) {
- super(activity);
+ public SilentBackgroundTask(Context context) {
+ super(context);
}
@Override
public void execute() {
- Thread thread = new Thread() {
- @Override
- public void run() {
- try {
- final T result = doInBackground();
-
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- done(result);
- }
- });
-
- } catch (final Throwable t) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- error(t);
- }
- });
- }
- }
- };
- thread.start();
+ queue.offer(task = new Task());
}
@Override
diff --git a/src/github/daneren2005/dsub/util/TabBackgroundTask.java b/src/github/daneren2005/dsub/util/TabBackgroundTask.java
index c345b982..bd76a2d4 100644
--- a/src/github/daneren2005/dsub/util/TabBackgroundTask.java
+++ b/src/github/daneren2005/dsub/util/TabBackgroundTask.java
@@ -19,40 +19,24 @@ public abstract class TabBackgroundTask<T> extends BackgroundTask<T> {
public void execute() {
tabFragment.setProgressVisible(true);
- new Thread() {
- @Override
- public void run() {
- try {
- final T result = doInBackground();
- if (isCancelled()) {
- return;
- }
-
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- tabFragment.setProgressVisible(false);
- done(result);
- }
- });
- } catch (final Throwable t) {
- if (isCancelled()) {
- return;
- }
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- tabFragment.setProgressVisible(false);
- error(t);
- }
- });
- }
- }
- }.start();
+ queue.offer(task = new Task() {
+ @Override
+ public void onDone(T result) {
+ tabFragment.setProgressVisible(false);
+ done(result);
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ tabFragment.setProgressVisible(false);
+ error(t);
+ }
+ });
}
- private boolean isCancelled() {
- return !tabFragment.isAdded();
+ @Override
+ protected boolean isCancelled() {
+ return !tabFragment.isAdded() || cancelled;
}
@Override
diff --git a/src/github/daneren2005/dsub/view/ErrorDialog.java b/src/github/daneren2005/dsub/view/ErrorDialog.java
index 246b3756..e72b1934 100644
--- a/src/github/daneren2005/dsub/view/ErrorDialog.java
+++ b/src/github/daneren2005/dsub/view/ErrorDialog.java
@@ -20,6 +20,7 @@ package github.daneren2005.dsub.view;
import android.app.Activity;
import android.app.AlertDialog;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -67,9 +68,9 @@ public class ErrorDialog {
}
}
- private void restart(Activity context) {
- Intent intent = new Intent(context, SubsonicFragmentActivity.class);
+ private void restart(Activity activity) {
+ Intent intent = new Intent(activity, SubsonicFragmentActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- Util.startActivityWithoutTransition(context, intent);
+ Util.startActivityWithoutTransition(activity, intent);
}
}