diff options
26 files changed, 395 insertions, 212 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/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java index 85eaafcad..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. @@ -80,6 +88,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc 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"; @@ -97,32 +106,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc 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 final PreferenceUI ui; - - private CheckBoxPreference[] selectedNetworks; - 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)) { @@ -130,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. @@ -144,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(); @@ -179,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 && @@ -440,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)); @@ -464,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 && diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 5f56b14df..fab96338e 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -289,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 e05e29229..ad88bb7bf 100644 --- a/build.gradle +++ b/build.gradle @@ -6,10 +6,10 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.1' - 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' + classpath "com.github.triplet.gradle:play-publisher:1.1.4" // Exclude the version that the android plugin depends on. configurations.classpath.exclude group: "com.android.tools.external.lombok" } 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/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/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/strings.xml b/core/src/main/res/values/strings.xml index 2347ce5f9..29cb9b610 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -451,6 +451,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…</string> <string name="export_error_label">Export error</string> <string name="opml_export_success_title">OPML Export successful.</string> |