summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java13
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java65
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java122
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java14
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java20
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java170
-rw-r--r--app/src/main/res/menu/episodes_apply_action_options.xml2
-rw-r--r--app/src/main/res/xml/preferences.xml11
-rw-r--r--build.gradle4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java29
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java30
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java92
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java (renamed from core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java)2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java (renamed from core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java)2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java21
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java (renamed from core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java)12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java19
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java43
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java2
-rw-r--r--core/src/main/res/values/arrays.xml2
-rw-r--r--core/src/main/res/values/strings.xml13
33 files changed, 519 insertions, 282 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
index bc1a40b11..355e0f372 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
@@ -15,7 +15,7 @@ import java.util.ArrayList;
import java.util.List;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.opml.OpmlElement;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
import de.danoeh.antennapod.core.preferences.UserPreferences;
/**
@@ -23,10 +23,8 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
* which feeds he wants to import.
*/
public class OpmlFeedChooserActivity extends AppCompatActivity {
- private static final String TAG = "OpmlFeedChooserActivity";
-
public static final String EXTRA_SELECTED_ITEMS = "de.danoeh.antennapod.selectedItems";
-
+ private static final String TAG = "OpmlFeedChooserActivity";
private Button butConfirm;
private Button butCancel;
private ListView feedlist;
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
index 8726af281..8b87aaaaf 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
@@ -20,7 +20,7 @@ import java.util.ArrayList;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.asynctask.OpmlFeedQueuer;
import de.danoeh.antennapod.asynctask.OpmlImportWorker;
-import de.danoeh.antennapod.core.opml.OpmlElement;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
import de.danoeh.antennapod.core.util.LangUtils;
/**
@@ -29,9 +29,8 @@ import de.danoeh.antennapod.core.util.LangUtils;
public class OpmlImportBaseActivity extends AppCompatActivity {
private static final String TAG = "OpmlImportBaseActivity";
- private OpmlImportWorker importWorker;
-
private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 5;
+ private OpmlImportWorker importWorker;
@Nullable private Uri uri;
/**
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java
index 7afa270cc..b01cf43e4 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java
@@ -1,9 +1,9 @@
package de.danoeh.antennapod.activity;
-import de.danoeh.antennapod.core.opml.OpmlElement;
-
import java.util.ArrayList;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
+
/**
* Hold infos gathered by Ompl-Import
* <p/>
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
index 61765d6b7..dd932814f 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
@@ -26,11 +26,9 @@ import de.danoeh.antennapod.preferences.PreferenceController;
*/
public class PreferenceActivity extends AppCompatActivity {
+ private static WeakReference<PreferenceActivity> instance;
private PreferenceController preferenceController;
private MainFragment prefFragment;
- private static WeakReference<PreferenceActivity> instance;
-
-
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
@@ -128,5 +126,14 @@ public class PreferenceActivity extends AppCompatActivity {
}
super.onPause();
}
+
+ @Override
+ public void onStop() {
+ PreferenceActivity activity = instance.get();
+ if(activity != null && activity.preferenceController != null) {
+ activity.preferenceController.onStop();
+ }
+ super.onStop();
+ }
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java
index 4af988ea0..390bec15c 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java
@@ -18,9 +18,6 @@ import de.danoeh.antennapod.preferences.PreferenceController;
*/
public class PreferenceActivityGingerbread extends android.preference.PreferenceActivity {
private static final String TAG = "PreferenceActivity";
-
- private PreferenceController preferenceController;
-
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
@SuppressWarnings("deprecation")
@@ -34,6 +31,7 @@ public class PreferenceActivityGingerbread extends android.preference.Preference
return PreferenceActivityGingerbread.this;
}
};
+ private PreferenceController preferenceController;
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
@@ -61,6 +59,12 @@ public class PreferenceActivityGingerbread extends android.preference.Preference
}
@Override
+ protected void onStop() {
+ preferenceController.onStop();
+ super.onStop();
+ }
+
+ @Override
protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
theme.applyStyle(UserPreferences.getTheme(), true);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java
new file mode 100644
index 000000000..192df8ca5
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java
@@ -0,0 +1,65 @@
+package de.danoeh.antennapod.asynctask;
+
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.util.LangUtils;
+import rx.Observable;
+
+/**
+ * Writes an OPML file into the export directory in the background.
+ */
+public class ExportWorker {
+
+ private static final String EXPORT_DIR = "export/";
+ private static final String TAG = "ExportWorker";
+ private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds";
+
+ private ExportWriter exportWriter;
+ private File output;
+
+ public ExportWorker(ExportWriter exportWriter) {
+ this(exportWriter, new File(UserPreferences.getDataFolder(EXPORT_DIR),
+ DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension()));
+ }
+
+ public ExportWorker(ExportWriter exportWriter, @NonNull File output) {
+ this.exportWriter = exportWriter;
+ this.output = output;
+ }
+
+ public Observable<File> exportObservable() {
+ if (output.exists()) {
+ Log.w(TAG, "Overwriting previously exported file.");
+ output.delete();
+ }
+ return Observable.create(subscriber -> {
+ OutputStreamWriter writer = null;
+ try {
+ writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8);
+ exportWriter.writeDocument(DBReader.getFeedList(), writer);
+ subscriber.onNext(output);
+ } catch (IOException e) {
+ subscriber.onError(e);
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ subscriber.onError(e);
+ }
+ }
+ subscriber.onCompleted();
+ }
+ });
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
deleted file mode 100644
index 13abb26ea..000000000
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package de.danoeh.antennapod.asynctask;
-
-import android.annotation.SuppressLint;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.support.v7.app.AlertDialog;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-
-import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.opml.OpmlWriter;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.storage.DBReader;
-import de.danoeh.antennapod.core.util.LangUtils;
-
-/**
- * Writes an OPML file into the export directory in the background.
- */
-public class OpmlExportWorker extends AsyncTask<Void, Void, Void> {
- private static final String TAG = "OpmlExportWorker";
- private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds.opml";
- public static final String EXPORT_DIR = "export/";
-
- private Context context;
- private File output;
-
- private ProgressDialog progDialog;
- private Exception exception;
-
- public OpmlExportWorker(Context context, File output) {
- this.context = context;
- this.output = output;
- }
-
- public OpmlExportWorker(Context context) {
- this.context = context;
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- OpmlWriter opmlWriter = new OpmlWriter();
- if (output == null) {
- output = new File(
- UserPreferences.getDataFolder(EXPORT_DIR),
- DEFAULT_OUTPUT_NAME);
- if (output.exists()) {
- Log.w(TAG, "Overwriting previously exported file.");
- output.delete();
- }
- }
- OutputStreamWriter writer = null;
- try {
- writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8);
- opmlWriter.writeDocument(DBReader.getFeedList(), writer);
- } catch (IOException e) {
- e.printStackTrace();
- exception = e;
- } finally {
- if (writer != null) {
- try {
- writer.close();
- } catch (IOException ioe) {
- exception = ioe;
- }
- }
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- progDialog.dismiss();
- AlertDialog.Builder alert = new AlertDialog.Builder(context)
- .setNeutralButton(android.R.string.ok,
- (dialog, which) -> dialog.dismiss());
- if (exception != null) {
- alert.setTitle(R.string.export_error_label);
- alert.setMessage(exception.getMessage());
- } else {
- alert.setTitle(R.string.opml_export_success_title);
- alert.setMessage(context
- .getString(R.string.opml_export_success_sum)
- + output.toString())
- .setPositiveButton(R.string.send_label, (dialog, which) -> {
- Uri outputUri = Uri.fromFile(output);
- Intent sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_SUBJECT,
- context.getResources().getText(R.string.opml_export_label));
- sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri);
- sendIntent.setType("text/plain");
- context.startActivity(Intent.createChooser(sendIntent,
- context.getResources().getText(R.string.send_label)));
- });
- }
- alert.create().show();
- }
-
- @Override
- protected void onPreExecute() {
- progDialog = new ProgressDialog(context);
- progDialog.setMessage(context.getString(R.string.exporting_label));
- progDialog.setIndeterminate(true);
- progDialog.show();
- }
-
- @SuppressLint("NewApi")
- public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
- }
-
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
index 1cb653f01..4449d82c2 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
@@ -9,8 +9,8 @@ import java.util.Arrays;
import de.danoeh.antennapod.activity.OpmlImportHolder;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.opml.OpmlElement;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
index f3b3aeca9..62ea85811 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
@@ -14,8 +14,8 @@ import java.io.Reader;
import java.util.ArrayList;
import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.opml.OpmlElement;
-import de.danoeh.antennapod.core.opml.OpmlReader;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
+import de.danoeh.antennapod.core.export.opml.OpmlReader;
public class OpmlImportWorker extends
AsyncTask<Void, Void, ArrayList<OpmlElement>> {
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
index 577a3ecbe..202d33408 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -225,6 +225,9 @@ public class EpisodesApplyActionFragment extends Fragment {
checkQueued(false);
resId = R.string.selected_not_queued_label;
break;
+ case R.id.check_has_media:
+ checkWithMedia();
+ resId = R.string.selected_has_media_label;
case R.id.sort_title_a_z:
sortByTitle(false);
return true;
@@ -357,6 +360,17 @@ public class EpisodesApplyActionFragment extends Fragment {
refreshCheckboxes();
}
+ private void checkWithMedia() {
+ for (FeedItem episode : episodes) {
+ if(episode.hasMedia()) {
+ checkedIds.add(episode.getId());
+ } else {
+ checkedIds.remove(episode.getId());
+ }
+ }
+ refreshCheckboxes();
+ }
+
private void refreshTitles() {
titles.clear();
for(FeedItem episode : episodes) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
index 29df6617d..ab8808093 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -227,22 +227,32 @@ public class AllEpisodesFragment extends Fragment {
}
return true;
case R.id.mark_all_read_item:
- ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(),
+ ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(),
R.string.mark_all_read_label,
R.string.mark_all_read_confirmation_msg) {
@Override
- public void onConfirmButtonPressed(
- DialogInterface dialog) {
+ public void onConfirmButtonPressed(DialogInterface dialog) {
dialog.dismiss();
DBWriter.markAllItemsRead();
Toast.makeText(getActivity(), R.string.mark_all_read_msg, Toast.LENGTH_SHORT).show();
}
};
- conDialog.createNewDialog().show();
+ markAllReadConfirmationDialog.createNewDialog().show();
return true;
case R.id.mark_all_seen_item:
- DBWriter.markNewItemsSeen();
+ ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(getActivity(),
+ R.string.mark_all_seen_label,
+ R.string.mark_all_seen_confirmation_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ DBWriter.markNewItemsSeen();
+ Toast.makeText(getActivity(), R.string.mark_all_seen_msg, Toast.LENGTH_SHORT).show();
+ }
+ };
+ markAllSeenConfirmationDialog.createNewDialog().show();
return true;
default:
return false;
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
index 19b8361e6..818b3a625 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.preferences;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.app.ProgressDialog;
import android.app.TimePickerDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -54,7 +55,10 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.activity.PreferenceActivityGingerbread;
import de.danoeh.antennapod.activity.StatisticsActivity;
-import de.danoeh.antennapod.asynctask.OpmlExportWorker;
+import de.danoeh.antennapod.asynctask.ExportWorker;
+import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.export.html.HtmlWriter;
+import de.danoeh.antennapod.core.export.opml.OpmlWriter;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.GpodnetSyncService;
@@ -66,6 +70,10 @@ import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog;
import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
import de.danoeh.antennapod.dialog.ProxyDialog;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
+import rx.Observable;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
/**
* Sets up a preference UI that lets the user change user preferences.
@@ -75,53 +83,34 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
private static final String TAG = "PreferenceController";
- public static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
- public static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
- public static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
- public static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
- public static final String PREF_OPML_EXPORT = "prefOpmlExport";
- public static final String STATISTICS = "statistics";
- public static final String PREF_ABOUT = "prefAbout";
- public static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
- public static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
- public static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
- public static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
- public static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
- public static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
- public static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
- public static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
- public static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications";
- public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
- public static final String PREF_PROXY = "prefProxy";
- public static final String PREF_KNOWN_ISSUES = "prefKnownIssues";
- public static final String PREF_FAQ = "prefFaq";
- public static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport";
-
- private final PreferenceUI ui;
-
- private CheckBoxPreference[] selectedNetworks;
-
+ private static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
+ private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
+ private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
+ private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
+ private static final String PREF_OPML_EXPORT = "prefOpmlExport";
+ private static final String PREF_HTML_EXPORT = "prefHtmlExport";
+ private static final String STATISTICS = "statistics";
+ private static final String PREF_ABOUT = "prefAbout";
+ private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
+ private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
+ private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
+ private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
+ private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
+ private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
+ private static final String PREF_GPODNET_FORCE_FULL_SYNC = "pref_gpodnet_force_full_sync";
+ private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
+ private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
+ private static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications";
+ private static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
+ private static final String PREF_PROXY = "prefProxy";
+ private static final String PREF_KNOWN_ISSUES = "prefKnownIssues";
+ private static final String PREF_FAQ = "prefFaq";
+ private static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport";
private static final String[] EXTERNAL_STORAGE_PERMISSIONS = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE };
private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41;
-
- public PreferenceController(PreferenceUI ui) {
- this.ui = ui;
- PreferenceManager.getDefaultSharedPreferences(ui.getActivity().getApplicationContext())
- .registerOnSharedPreferenceChangeListener(this);
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if(key.equals(UserPreferences.PREF_SONIC)) {
- CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC);
- if(prefSonic != null) {
- prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false));
- }
- }
- }
-
+ private final PreferenceUI ui;
private final SharedPreferences.OnSharedPreferenceChangeListener gpoddernetListener =
(sharedPreferences, key) -> {
if (GpodnetPreferences.PREF_LAST_SYNC_ATTEMPT_TIMESTAMP.equals(key)) {
@@ -129,6 +118,14 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
GpodnetPreferences.getLastSyncAttemptTimestamp());
}
};
+ private CheckBoxPreference[] selectedNetworks;
+ private Subscription subscription;
+
+ public PreferenceController(PreferenceUI ui) {
+ this.ui = ui;
+ PreferenceManager.getDefaultSharedPreferences(ui.getActivity().getApplicationContext())
+ .registerOnSharedPreferenceChangeListener(this);
+ }
/**
* Returns the preference activity that should be used on this device.
@@ -143,6 +140,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
}
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if(key.equals(UserPreferences.PREF_SONIC)) {
+ CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC);
+ if(prefSonic != null) {
+ prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false));
+ }
+ }
+ }
+
public void onCreate() {
final Activity activity = ui.getActivity();
@@ -178,11 +185,9 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
);
ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener(
- preference -> {
- new OpmlExportWorker(activity).executeAsync();
- return true;
- }
- );
+ preference -> export(new OpmlWriter()));
+ ui.findPreference(PreferenceController.PREF_HTML_EXPORT).setOnPreferenceClickListener(
+ preference -> export(new HtmlWriter()));
ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
preference -> {
if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT &&
@@ -348,6 +353,18 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
toast.show();
return true;
});
+ ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).
+ setOnPreferenceClickListener(preference -> {
+ GpodnetPreferences.setLastSubscriptionSyncTimestamp(0L);
+ GpodnetPreferences.setLastEpisodeActionsSyncTimestamp(0L);
+ GpodnetPreferences.setLastSyncAttempt(false, 0);
+ updateLastGpodnetSyncReport(false, 0);
+ GpodnetSyncService.sendSyncIntent(ui.getActivity().getApplicationContext());
+ Toast toast = Toast.makeText(ui.getActivity(), R.string.pref_gpodnet_sync_started,
+ Toast.LENGTH_SHORT);
+ toast.show();
+ return true;
+ });
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setOnPreferenceClickListener(
preference -> {
GpodnetPreferences.logout();
@@ -427,6 +444,40 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter());
}
+ private boolean export(ExportWriter exportWriter) {
+ Context context = ui.getActivity();
+ final ProgressDialog progressDialog = new ProgressDialog(context);
+ progressDialog.setMessage(context.getString(R.string.exporting_label));
+ progressDialog.setIndeterminate(true);
+ progressDialog.show();
+ final AlertDialog.Builder alert = new AlertDialog.Builder(context)
+ .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
+ Observable<File> observable = new ExportWorker(exportWriter).exportObservable();
+ subscription = observable.subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(output -> {
+ alert.setTitle(R.string.opml_export_success_title);
+ String message = context.getString(R.string.opml_export_success_sum) + output.toString();
+ alert.setMessage(message);
+ alert.setPositiveButton(R.string.send_label, (dialog, which) -> {
+ Uri outputUri = Uri.fromFile(output);
+ Intent sendIntent = new Intent(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_SUBJECT,
+ context.getResources().getText(R.string.opml_export_label));
+ sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri);
+ sendIntent.setType("text/plain");
+ context.startActivity(Intent.createChooser(sendIntent,
+ context.getResources().getText(R.string.send_label)));
+ });
+ alert.create().show();
+ }, error -> {
+ alert.setTitle(R.string.export_error_label);
+ alert.setMessage(error.getMessage());
+ alert.show();
+ }, () -> progressDialog.dismiss());
+ return true;
+ }
+
private void openInBrowser(String url) {
try {
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
@@ -451,6 +502,12 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener);
}
+ public void onStop() {
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ }
+
@SuppressLint("NewApi")
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK &&
@@ -492,6 +549,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn);
ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn);
ui.findPreference(PreferenceController.PREF_GPODNET_SYNC).setEnabled(loggedIn);
+ ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).setEnabled(loggedIn);
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setEnabled(loggedIn);
ui.findPreference(PREF_GPODNET_NOTIFICATIONS).setEnabled(loggedIn);
if(loggedIn) {
@@ -511,7 +569,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
private void updateLastGpodnetSyncReport(boolean successful, long lastTime) {
Preference sync = ui.findPreference(PREF_GPODNET_SYNC);
if (lastTime != 0) {
- sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_sum) + "\n" +
+ sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum) + "\n" +
ui.getActivity().getString(R.string.pref_gpodnet_sync_sum_last_sync_line,
ui.getActivity().getString(successful ?
R.string.gpodnetsync_pref_report_successful :
@@ -522,7 +580,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
DateUtils.WEEK_IN_MILLIS,
DateUtils.FORMAT_SHOW_TIME)));
} else {
- sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_sum));
+ sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum));
}
}
@@ -774,9 +832,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
}
});
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
- });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) ->
+ UserPreferences.setHiddenDrawerItems(hiddenDrawerItems));
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
}
@@ -820,9 +877,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
preferredButtons.remove((Integer) which);
}
});
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setCompactNotificationButtons(preferredButtons);
- });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) ->
+ UserPreferences.setCompactNotificationButtons(preferredButtons));
builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show();
}
diff --git a/app/src/main/res/menu/episodes_apply_action_options.xml b/app/src/main/res/menu/episodes_apply_action_options.xml
index 3df88046d..c3f117386 100644
--- a/app/src/main/res/menu/episodes_apply_action_options.xml
+++ b/app/src/main/res/menu/episodes_apply_action_options.xml
@@ -46,6 +46,8 @@
android:title="@string/queued_label"/>
<item android:id="@+id/check_not_queued"
android:title="@string/not_queued_label"/>
+ <item android:id="@+id/check_has_media"
+ android:title="@string/has_media"/>
</menu>
</item>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 350e2e2ee..fab96338e 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -253,8 +253,12 @@
android:summary="@string/pref_gpodnet_setlogin_information_sum"/>
<Preference
android:key="pref_gpodnet_sync"
- android:title="@string/pref_gpodnet_sync_title"
- android:summary="@string/pref_gpodnet_sync_sum"/>
+ android:title="@string/pref_gpodnet_sync_changes_title"
+ android:summary="@string/pref_gpodnet_sync_changes_sum"/>
+ <Preference
+ android:key="pref_gpodnet_force_full_sync"
+ android:title="@string/pref_gpodnet_full_sync_title"
+ android:summary="@string/pref_gpodnet_full_sync_sum"/>
<Preference
android:key="pref_gpodnet_logout"
android:title="@string/pref_gpodnet_logout_title"/>
@@ -285,6 +289,9 @@
android:key="prefOpmlExport"
android:title="@string/opml_export_label"/>
<Preference
+ android:key="prefHtmlExport"
+ android:title="@string/html_export_label"/>
+ <Preference
android:key="statistics"
android:title="@string/statistics_label"/>
</PreferenceCategory>
diff --git a/build.gradle b/build.gradle
index 221f5a68c..eddcd91d5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,8 +6,8 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.2.0'
- classpath "me.tatarka:gradle-retrolambda:3.3.0"
+ classpath 'com.android.tools.build:gradle:2.2.2'
+ classpath "me.tatarka:gradle-retrolambda:3.3.1"
classpath "me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2"
classpath 'com.github.triplet.gradle:play-publisher:1.1.4'
// Exclude the version that the android plugin depends on.
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java
index e475e696c..67c460e78 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java
@@ -38,10 +38,11 @@ public class FeedRemover extends AsyncTask<Void, Void, Void> {
@Override
protected void onPostExecute(Void result) {
- dialog.dismiss();
+ if(dialog != null && dialog.isShowing()) {
+ dialog.dismiss();
+ }
if(skipOnCompletion) {
- context.sendBroadcast(new Intent(
- PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
+ context.sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java
index 982015314..80ce6cf56 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java
@@ -8,6 +8,7 @@ import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.util.Log;
+import org.apache.commons.io.IOUtils;
import org.xmlpull.v1.XmlPullParserException;
import java.io.ByteArrayOutputStream;
@@ -27,10 +28,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import de.danoeh.antennapod.core.BuildConfig;
+import de.danoeh.antennapod.core.export.opml.OpmlElement;
+import de.danoeh.antennapod.core.export.opml.OpmlReader;
+import de.danoeh.antennapod.core.export.opml.OpmlWriter;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.opml.OpmlElement;
-import de.danoeh.antennapod.core.opml.OpmlReader;
-import de.danoeh.antennapod.core.opml.OpmlWriter;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
@@ -56,7 +57,9 @@ public class OpmlBackupAgent extends BackupAgentHelper {
}
}
- /** Class for backing up and restoring the OPML file. */
+ /**
+ * Class for backing up and restoring the OPML file.
+ */
private static class OpmlBackupHelper implements BackupHelper {
private static final String TAG = "OpmlBackupHelper";
@@ -64,7 +67,9 @@ public class OpmlBackupAgent extends BackupAgentHelper {
private final Context mContext;
- /** Checksum of restored OPML file */
+ /**
+ * Checksum of restored OPML file
+ */
private byte[] mChecksum;
public OpmlBackupHelper(Context context) {
@@ -170,12 +175,7 @@ public class OpmlBackupAgent extends BackupAgentHelper {
} catch (IOException e) {
Log.e(TAG, "Failed to restore OPML backup", e);
} finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- }
- }
+ IOUtils.closeQuietly(reader);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java
new file mode 100644
index 000000000..020a0671f
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/CommonSymbols.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package de.danoeh.antennapod.core.export;
+
+public class CommonSymbols {
+
+ public static final String HEAD = "head";
+ public static final String BODY = "body";
+ public static final String TITLE = "title";
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java
new file mode 100644
index 000000000..d6a187b21
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package de.danoeh.antennapod.core.export;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+
+import de.danoeh.antennapod.core.feed.Feed;
+
+public interface ExportWriter {
+
+ void writeDocument(List<Feed> feeds, Writer writer)
+ throws IllegalArgumentException, IllegalStateException, IOException;
+
+ String fileExtension();
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java
new file mode 100644
index 000000000..b8807a686
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package de.danoeh.antennapod.core.export.html;
+
+import de.danoeh.antennapod.core.export.CommonSymbols;
+
+class HtmlSymbols extends CommonSymbols {
+
+ static final String HTML = "html";
+
+ static final String ORDERED_LIST = "ol";
+ static final String LIST_ITEM = "li";
+
+ static String HEADING = "h1";
+
+ static final String LINK = "a";
+ static final String LINK_DESTINATION = "href";
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java
new file mode 100644
index 000000000..2fdd8ffa6
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java
@@ -0,0 +1,92 @@
+package de.danoeh.antennapod.core.export.html;
+
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+
+import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.feed.Feed;
+
+/** Writes HTML documents. */
+public class HtmlWriter implements ExportWriter {
+
+ private static final String TAG = "HtmlWriter";
+ private static final String ENCODING = "UTF-8";
+ private static final String HTML_TITLE = "AntennaPod Subscriptions";
+
+ /**
+ * Takes a list of feeds and a writer and writes those into an HTML
+ * document.
+ *
+ * @throws IOException
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ */
+ @Override
+ public void writeDocument(List<Feed> feeds, Writer writer)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ Log.d(TAG, "Starting to write document");
+ XmlSerializer xs = Xml.newSerializer();
+ xs.setOutput(writer);
+
+ xs.startDocument(ENCODING, false);
+ xs.text("\n");
+ xs.startTag(null, HtmlSymbols.HTML);
+ xs.text("\n");
+ xs.startTag(null, HtmlSymbols.HEAD);
+ xs.text("\n");
+ xs.startTag(null, HtmlSymbols.TITLE);
+ xs.text(HTML_TITLE);
+ xs.endTag(null, HtmlSymbols.TITLE);
+ xs.text("\n");
+ xs.endTag(null, HtmlSymbols.HEAD);
+ xs.text("\n");
+
+ xs.startTag(null, HtmlSymbols.BODY);
+ xs.text("\n");
+ xs.startTag(null, HtmlSymbols.HEADING);
+ xs.text(HTML_TITLE);
+ xs.endTag(null, HtmlSymbols.HEADING);
+ xs.text("\n");
+ xs.startTag(null, HtmlSymbols.ORDERED_LIST);
+ xs.text("\n");
+ for (Feed feed : feeds) {
+ xs.startTag(null, HtmlSymbols.LIST_ITEM);
+ xs.text(feed.getTitle());
+ if (!TextUtils.isEmpty(feed.getLink())) {
+ xs.text(" [");
+ xs.startTag(null, HtmlSymbols.LINK);
+ xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getLink());
+ xs.text("Website");
+ xs.endTag(null, HtmlSymbols.LINK);
+ xs.text("]");
+ }
+ xs.text(" [");
+ xs.startTag(null, HtmlSymbols.LINK);
+ xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getDownload_url());
+ xs.text("Feed");
+ xs.endTag(null, HtmlSymbols.LINK);
+ xs.text("]");
+ xs.endTag(null, HtmlSymbols.LIST_ITEM);
+ xs.text("\n");
+ }
+ xs.endTag(null, HtmlSymbols.ORDERED_LIST);
+ xs.endTag(null, HtmlSymbols.BODY);
+ xs.text("\n");
+ xs.endTag(null, HtmlSymbols.HTML);
+ xs.text("\n");
+ xs.endDocument();
+ Log.d(TAG, "Finished writing document");
+ }
+
+ public String fileExtension() {
+ return "html";
+ }
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java
index 8d0a4a842..61eb4d0c9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlElement.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlElement.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.opml;
+package de.danoeh.antennapod.core.export.opml;
/** Represents a single feed in an OPML file. */
public class OpmlElement {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java
index 17afc7904..a17fedd7d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlReader.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.opml;
+package de.danoeh.antennapod.core.export.opml;
import android.util.Log;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java
new file mode 100644
index 000000000..40b0e23b8
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlSymbols.java
@@ -0,0 +1,21 @@
+package de.danoeh.antennapod.core.export.opml;
+
+import de.danoeh.antennapod.core.export.CommonSymbols;
+
+/** Contains symbols for reading and writing OPML documents. */
+public final class OpmlSymbols extends CommonSymbols {
+
+ public static final String OPML = "opml";
+ static final String OUTLINE = "outline";
+ static final String TEXT = "text";
+ static final String XMLURL = "xmlUrl";
+ static final String HTMLURL = "htmlUrl";
+ static final String TYPE = "type";
+ static final String VERSION = "version";
+ static final String DATE_CREATED = "dateCreated";
+
+ private OpmlSymbols() {
+
+ }
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java
index 673c602df..afd652cff 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.opml;
+package de.danoeh.antennapod.core.export.opml;
import android.util.Log;
import android.util.Xml;
@@ -10,11 +10,13 @@ import java.io.Writer;
import java.util.Date;
import java.util.List;
+import de.danoeh.antennapod.core.export.ExportWriter;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.util.DateUtils;
/** Writes OPML documents. */
-public class OpmlWriter {
+public class OpmlWriter implements ExportWriter {
+
private static final String TAG = "OpmlWriter";
private static final String ENCODING = "UTF-8";
private static final String OPML_VERSION = "2.0";
@@ -28,6 +30,7 @@ public class OpmlWriter {
* @throws IllegalStateException
* @throws IllegalArgumentException
*/
+ @Override
public void writeDocument(List<Feed> feeds, Writer writer)
throws IllegalArgumentException, IllegalStateException, IOException {
Log.d(TAG, "Starting to write document");
@@ -83,4 +86,9 @@ public class OpmlWriter {
xs.endDocument();
Log.d(TAG, "Finished writing document");
}
+
+ public String fileExtension() {
+ return "opml";
+ }
+
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
index 9d8f4adf8..200153876 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
@@ -18,6 +18,7 @@ public class FeedItemFilter {
private boolean showNotQueued = false;
private boolean showDownloaded = false;
private boolean showNotDownloaded = false;
+ private boolean showHasMedia = false;
public FeedItemFilter(String properties) {
this(TextUtils.split(properties, ","));
@@ -49,6 +50,9 @@ public class FeedItemFilter {
case "not_downloaded":
showNotDownloaded = true;
break;
+ case "has_media":
+ showHasMedia = true;
+ break;
}
}
}
@@ -82,6 +86,8 @@ public class FeedItemFilter {
if (showDownloaded && !downloaded) continue;
if (showNotDownloaded && downloaded) continue;
+ if (showHasMedia && !item.hasMedia()) continue;
+
// If the item reaches here, it meets all criteria
result.add(item);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java
deleted file mode 100644
index c973713cb..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.danoeh.antennapod.core.opml;
-
-/** Contains symbols for reading and writing OPML documents. */
-public final class OpmlSymbols {
-
- public static final String OPML = "opml";
- public static final String BODY = "body";
- public static final String OUTLINE = "outline";
- public static final String TEXT = "text";
- public static final String XMLURL = "xmlUrl";
- public static final String HTMLURL = "htmlUrl";
- public static final String TYPE = "type";
- public static final String VERSION = "version";
- public static final String HEAD = "head";
- public static final String TITLE = "title";
- public static final String DATE_CREATED = "dateCreated";
-
- private OpmlSymbols() {
-
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
index 0871758d0..cad67539b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
@@ -383,6 +383,9 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
statusBeforeSeeking = playerStatus;
setPlayerStatus(PlayerStatus.SEEKING, media, getPosition());
mediaPlayer.seekTo(t);
+ if (statusBeforeSeeking == PlayerStatus.PREPARED) {
+ media.setPosition(t);
+ }
try {
seekLatch.await(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java
index 47503dee4..ae91c0743 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java
@@ -6,7 +6,6 @@ import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
-import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.syndication.namespace.NSContent;
import de.danoeh.antennapod.core.syndication.namespace.NSDublinCore;
@@ -86,34 +85,28 @@ public class SyndHandler extends DefaultHandler {
state.defaultNamespaces.push(new NSAtom());
} else if (prefix.equals(NSAtom.NSTAG)) {
state.namespaces.put(uri, new NSAtom());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized Atom namespace");
+ Log.d(TAG, "Recognized Atom namespace");
}
} else if (uri.equals(NSContent.NSURI)
&& prefix.equals(NSContent.NSTAG)) {
state.namespaces.put(uri, new NSContent());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized Content namespace");
+ Log.d(TAG, "Recognized Content namespace");
} else if (uri.equals(NSITunes.NSURI)
&& prefix.equals(NSITunes.NSTAG)) {
state.namespaces.put(uri, new NSITunes());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized ITunes namespace");
+ Log.d(TAG, "Recognized ITunes namespace");
} else if (uri.equals(NSSimpleChapters.NSURI)
&& prefix.matches(NSSimpleChapters.NSTAG)) {
state.namespaces.put(uri, new NSSimpleChapters());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized SimpleChapters namespace");
+ Log.d(TAG, "Recognized SimpleChapters namespace");
} else if (uri.equals(NSMedia.NSURI)
&& prefix.equals(NSMedia.NSTAG)) {
state.namespaces.put(uri, new NSMedia());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized media namespace");
+ Log.d(TAG, "Recognized media namespace");
} else if (uri.equals(NSDublinCore.NSURI)
&& prefix.equals(NSDublinCore.NSTAG)) {
state.namespaces.put(uri, new NSDublinCore());
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Recognized DublinCore namespace");
+ Log.d(TAG, "Recognized DublinCore namespace");
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
index a5ca9d6f4..c91444552 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
@@ -20,25 +20,27 @@ import de.danoeh.antennapod.core.util.DateUtils;
*
*/
public class NSRSS20 extends Namespace {
- private static final String TAG = "NSRSS20";
- public static final String NSTAG = "rss";
- public static final String NSURI = "";
- public static final String CHANNEL = "channel";
+ private static final String TAG = "NSRSS20";
+
+ private static final String NSTAG = "rss";
+ private static final String NSURI = "";
+
+ public static final String CHANNEL = "channel";
public static final String ITEM = "item";
- public static final String GUID = "guid";
- public static final String TITLE = "title";
- public static final String LINK = "link";
- public static final String DESCR = "description";
- public static final String PUBDATE = "pubDate";
- public static final String ENCLOSURE = "enclosure";
- public static final String IMAGE = "image";
- public static final String URL = "url";
- public static final String LANGUAGE = "language";
+ private static final String GUID = "guid";
+ private static final String TITLE = "title";
+ private static final String LINK = "link";
+ private static final String DESCR = "description";
+ private static final String PUBDATE = "pubDate";
+ private static final String ENCLOSURE = "enclosure";
+ private static final String IMAGE = "image";
+ private static final String URL = "url";
+ private static final String LANGUAGE = "language";
- public static final String ENC_URL = "url";
- public static final String ENC_LEN = "length";
- public static final String ENC_TYPE = "type";
+ private static final String ENC_URL = "url";
+ private static final String ENC_LEN = "length";
+ private static final String ENC_TYPE = "type";
@Override
public SyndElement handleElementStart(String localName, HandlerState state,
@@ -55,11 +57,12 @@ public class NSRSS20 extends Namespace {
if(SyndTypeUtils.enclosureTypeValid(type)) {
validType = true;
} else {
- type = type = SyndTypeUtils.getValidMimeTypeFromUrl(url);
+ type = SyndTypeUtils.getValidMimeTypeFromUrl(url);
validType = type != null;
}
+ boolean validUrl = !TextUtils.isEmpty(url);
if (state.getCurrentItem() != null && state.getCurrentItem().getMedia() == null &&
- validType) {
+ validType && validUrl) {
long size = 0;
try {
size = Long.parseLong(attributes.getValue(ENC_LEN));
@@ -70,8 +73,8 @@ public class NSRSS20 extends Namespace {
} catch (NumberFormatException e) {
Log.d(TAG, "Length attribute could not be parsed.");
}
- state.getCurrentItem().setMedia(
- new FeedMedia(state.getCurrentItem(), url, size, type));
+ FeedMedia media = new FeedMedia(state.getCurrentItem(), url, size, type);
+ state.getCurrentItem().setMedia(media);
}
} else if (IMAGE.equals(localName)) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
index 13aadf027..6251cc4a0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
@@ -216,7 +216,7 @@ public abstract class PlaybackController {
Intent serviceIntent = new Intent(activity, PlaybackService.class);
serviceIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
serviceIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED, false);
- serviceIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, false);
+ serviceIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, true);
boolean fileExists = media.localFileAvailable();
boolean lastIsStream = PlaybackPreferences.getCurrentEpisodeIsStream();
if (!fileExists && !lastIsStream && media instanceof FeedMedia) {
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index 238169877..133a3ed6e 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -187,6 +187,7 @@
<item>@string/hide_not_queued_episodes_label</item>
<item>@string/hide_downloaded_episodes_label</item>
<item>@string/hide_not_downloaded_episodes_label</item>
+ <item>@string/hide_has_media_label</item>
</string-array>
<string-array name="episode_filter_values">
@@ -197,6 +198,7 @@
<item>not_queued</item>
<item>downloaded</item>
<item>not_downloaded</item>
+ <item>has_media</item>
</string-array>
<string-array name="image_cache_size_options">
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index c330756f1..8a92ab5b2 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -112,6 +112,8 @@
<string name="mark_all_read_confirmation_msg">Please confirm that you want to mark all episodes as being played.</string>
<string name="mark_all_read_feed_confirmation_msg">Please confirm that you want to mark all episodes in this feed as being played.</string>
<string name="mark_all_seen_label">Mark all as seen</string>
+ <string name="mark_all_seen_msg">Marked all Episodes as seen</string>
+ <string name="mark_all_seen_confirmation_msg">Please confirm that you want to mark all episodes as seen.</string>
<string name="show_info_label">Show information</string>
<string name="remove_feed_label">Remove Podcast</string>
<string name="share_label">Share&#8230;</string>
@@ -132,6 +134,7 @@
<string name="hide_not_queued_episodes_label">Not queued</string>
<string name="hide_downloaded_episodes_label">Downloaded</string>
<string name="hide_not_downloaded_episodes_label">Not downloaded</string>
+ <string name="hide_has_media_label">Has media</string>
<string name="filtered_label">Filtered</string>
<string name="refresh_failed_msg">{fa-exclamation-circle} Last Refresh failed</string>
<string name="open_podcast">Open Podcast</string>
@@ -367,10 +370,13 @@
<string name="pref_gpodnet_logout_toast">Logout was successful</string>
<string name="pref_gpodnet_setlogin_information_title">Change login information</string>
<string name="pref_gpodnet_setlogin_information_sum">Change the login information for your gpodder.net account.</string>
- <string name="pref_gpodnet_sync_title">Sync now</string>
- <string name="pref_gpodnet_sync_sum">Sync subscriptions and episode states with gpodder.net.</string>
+ <string name="pref_gpodnet_sync_changes_title">Sync changes now</string>
+ <string name="pref_gpodnet_sync_changes_sum">Sync subscription and episode state changes with gpodder.net.</string>
+ <string name="pref_gpodnet_full_sync_title">Full sync now</string>
+ <string name="pref_gpodnet_full_sync_sum">Sync all subscriptions and episode states with gpodder.net.</string>
<string name="pref_gpodnet_sync_sum_last_sync_line">Last sync attempt: %1$s (%2$s)</string>
<string name="pref_gpodnet_sync_started">Sync started</string>
+ <string name="pref_gpodnet_full_sync_started">Full sync started</string>
<string name="pref_gpodnet_login_status"><![CDATA[Logged in as <i>%1$s</i> with device <i>%2$s</i>]]></string>
<string name="pref_gpodnet_notifications_title">Show sync error notifications</string>
<string name="pref_gpodnet_notifications_sum">This setting does not apply to authentication errors.</string>
@@ -446,6 +452,7 @@
<string name="choose_file_from_filesystem">From local filesystem</string>
<string name="choose_file_from_external_application">Use external application</string>
<string name="opml_export_label">OPML export</string>
+ <string name="html_export_label">HTML export</string>
<string name="exporting_label">Exporting&#8230;</string>
<string name="export_error_label">Export error</string>
<string name="opml_export_success_title">OPML Export successful.</string>
@@ -588,6 +595,8 @@
<string name="selected_queued_label">Selected queued Episodes</string>
<string name="not_queued_label">Not queued</string>
<string name="selected_not_queued_label">Selected not queued Episodes</string>
+ <string name="has_media">Has media</string>
+ <string name="selected_has_media_label">Selected episodes with media</string>
<!-- Sort -->
<string name="sort_title_a_z">Title (A \u2192 Z)</string>