diff options
author | Martin Fietz <Martin.Fietz@gmail.com> | 2018-01-21 10:51:16 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-21 10:51:16 +0100 |
commit | e6498393a691367c031c5a09ff53d086a497d530 (patch) | |
tree | 777bce0831d93e02ba7fe7d813ba3a593a57921b /app/src | |
parent | 9adbf83182aa905d7e662783801fb87842716c93 (diff) | |
parent | dc316074e8b5c408c7dc7eff7b16f9ffd8978ac7 (diff) | |
download | AntennaPod-e6498393a691367c031c5a09ff53d086a497d530.zip |
Merge pull request #2445 from ByteHamster/export
Database import/export
Diffstat (limited to 'app/src')
5 files changed, 231 insertions, 0 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6be5bd1b3..8c3c86358 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -168,6 +168,13 @@ android:value="de.danoeh.antennapod.activity.PreferenceActivity"/> </activity> <activity + android:name=".activity.ImportExportActivity" + android:label="@string/import_export"> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value="de.danoeh.antennapod.activity.PreferenceActivity"/> + </activity> + <activity android:name=".activity.OpmlImportFromPathActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/opml_import_label"> diff --git a/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java new file mode 100644 index 000000000..6a97adcc3 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java @@ -0,0 +1,185 @@ +package de.danoeh.antennapod.activity; + +import android.content.ComponentName; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.os.ParcelFileDescriptor; +import android.support.design.widget.Snackbar; +import android.support.v4.content.IntentCompat; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.MenuItem; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.storage.PodDBAdapter; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.FileChannel; + +/** + * Displays the 'import/export' screen + */ +public class ImportExportActivity extends AppCompatActivity { + private static final int REQUEST_CODE_RESTORE = 43; + private static final int REQUEST_CODE_BACKUP_DOCUMENT = 44; + private static final String EXPORT_FILENAME = "AntennaPodBackup.db"; + private static final String TAG = ImportExportActivity.class.getSimpleName(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(UserPreferences.getTheme()); + super.onCreate(savedInstanceState); + getSupportActionBar().setDisplayShowHomeEnabled(true); + setContentView(R.layout.import_export_activity); + + findViewById(R.id.button_export).setOnClickListener(view -> backup()); + findViewById(R.id.button_import).setOnClickListener(view -> restore()); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } else { + return super.onOptionsItemSelected(item); + } + } + + private void backup() { + if (Build.VERSION.SDK_INT >= 19) { + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT) + .addCategory(Intent.CATEGORY_OPENABLE) + .setType("application/x-sqlite3") + .putExtra(Intent.EXTRA_TITLE, EXPORT_FILENAME); + + startActivityForResult(intent, REQUEST_CODE_BACKUP_DOCUMENT); + } else { + try { + File sd = Environment.getExternalStorageDirectory(); + File backupDB = new File(sd, EXPORT_FILENAME); + writeBackupTo(new FileOutputStream(backupDB)); + } catch (IOException e) { + Log.e(TAG, Log.getStackTraceString(e)); + Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show(); + } + } + } + + private void restore() { + if (Build.VERSION.SDK_INT >= 19) { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.setType("*/*"); + startActivityForResult(intent, REQUEST_CODE_RESTORE); + } else { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("*/*"); + startActivityForResult(Intent.createChooser(intent, + getString(R.string.import_select_file)), REQUEST_CODE_RESTORE); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent resultData) { + if (resultCode != RESULT_OK || resultData == null) { + return; + } + Uri uri = resultData.getData(); + + if (requestCode == REQUEST_CODE_RESTORE) { + restoreFrom(uri); + } else if (requestCode == REQUEST_CODE_BACKUP_DOCUMENT) { + backupToDocument(uri); + } + } + + private void restoreFrom(Uri inputUri) { + File currentDB = getDatabasePath(PodDBAdapter.DATABASE_NAME); + InputStream inputStream = null; + try { + inputStream = getContentResolver().openInputStream(inputUri); + FileUtils.copyInputStreamToFile(inputStream, currentDB); + displayImportSuccessDialog(); + } catch (IOException e) { + Log.e(TAG, Log.getStackTraceString(e)); + Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show(); + } finally { + IOUtils.closeQuietly(inputStream); + } + } + + private void displayImportSuccessDialog() { + AlertDialog.Builder d = new AlertDialog.Builder(ImportExportActivity.this); + d.setMessage(R.string.import_ok); + d.setCancelable(false); + d.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> { + Intent intent = new Intent(getApplicationContext(), SplashActivity.class); + ComponentName cn = intent.getComponent(); + Intent mainIntent = IntentCompat.makeRestartActivityTask(cn); + startActivity(mainIntent); + }); + d.show(); + } + + private void backupToDocument(Uri uri) { + ParcelFileDescriptor pfd = null; + FileOutputStream fileOutputStream = null; + try { + pfd = getContentResolver().openFileDescriptor(uri, "w"); + fileOutputStream = new FileOutputStream(pfd.getFileDescriptor()); + writeBackupTo(fileOutputStream); + + Snackbar.make(findViewById(R.id.import_export_layout), + R.string.export_ok, Snackbar.LENGTH_SHORT).show(); + } catch (IOException e) { + Log.e(TAG, Log.getStackTraceString(e)); + Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show(); + } finally { + IOUtils.closeQuietly(fileOutputStream); + + if (pfd != null) { + try { + pfd.close(); + } catch (IOException e) { + Log.d(TAG, "Unable to close ParcelFileDescriptor"); + } + } + } + } + + private void writeBackupTo(FileOutputStream outFileStream) { + FileChannel src = null; + FileChannel dst = null; + try { + File currentDB = getDatabasePath(PodDBAdapter.DATABASE_NAME); + + if (currentDB.exists()) { + src = new FileInputStream(currentDB).getChannel(); + dst = outFileStream.getChannel(); + dst.transferFrom(src, 0, src.size()); + + Snackbar.make(findViewById(R.id.import_export_layout), + R.string.export_ok, Snackbar.LENGTH_SHORT).show(); + } else { + Snackbar.make(findViewById(R.id.import_export_layout), + "Can not access current database", Snackbar.LENGTH_SHORT).show(); + } + } catch (IOException e) { + Log.e(TAG, Log.getStackTraceString(e)); + Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show(); + } finally { + IOUtils.closeQuietly(src); + IOUtils.closeQuietly(dst); + } + } +} 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 58c7f39a1..5da6f1fb0 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -38,6 +38,7 @@ import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; +import de.danoeh.antennapod.activity.ImportExportActivity; import org.apache.commons.lang3.ArrayUtils; import java.io.File; @@ -91,6 +92,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc 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 IMPORT_EXPORT = "importExport"; 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"; @@ -174,6 +176,12 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc return true; } ); + ui.findPreference(PreferenceController.IMPORT_EXPORT).setOnPreferenceClickListener( + preference -> { + activity.startActivity(new Intent(activity, ImportExportActivity.class)); + return true; + } + ); ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener( preference -> export(new OpmlWriter())); ui.findPreference(PreferenceController.PREF_HTML_EXPORT).setOnPreferenceClickListener( diff --git a/app/src/main/res/layout/import_export_activity.xml b/app/src/main/res/layout/import_export_activity.xml new file mode 100644 index 000000000..6614a8710 --- /dev/null +++ b/app/src/main/res/layout/import_export_activity.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:id="@+id/import_export_layout" + android:padding="8dp"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/import_export_warning" + android:gravity="center_horizontal"/> + + <Button + android:text="@string/label_export" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/button_export" + android:layout_marginTop="24dp"/> + + <Button + android:text="@string/label_import" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/button_import"/> + +</LinearLayout> diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index e81115627..8ed7da731 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -316,6 +316,9 @@ android:key="prefHtmlExport" android:title="@string/html_export_label"/> <Preference + android:key="importExport" + android:title="@string/import_export"/> + <Preference android:key="statistics" android:title="@string/statistics_label"/> </PreferenceCategory> |