Merge pull request #2158 from mfietz/feature/2154-export-html
Export subscriptions as HTML
This commit is contained in:
commit
ff5b136351
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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/>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
@ -60,6 +58,12 @@ public class PreferenceActivityGingerbread extends android.preference.Preference
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
preferenceController.onStop();
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
|
||||
theme.applyStyle(UserPreferences.getTheme(), true);
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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>> {
|
||||
|
@ -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 &&
|
||||
|
@ -288,6 +288,9 @@
|
||||
<Preference
|
||||
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"/>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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";
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
@ -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 {
|
@ -1,4 +1,4 @@
|
||||
package de.danoeh.antennapod.core.opml;
|
||||
package de.danoeh.antennapod.core.export.opml;
|
||||
|
||||
import android.util.Log;
|
||||
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user