diff --git a/app/src/main/java/protect/card_locker/ImportExportTask.java b/app/src/main/java/protect/card_locker/ImportExportTask.java new file mode 100644 index 000000000..a3fd3c58f --- /dev/null +++ b/app/src/main/java/protect/card_locker/ImportExportTask.java @@ -0,0 +1,146 @@ +package protect.card_locker; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.os.AsyncTask; +import android.os.Environment; +import android.util.Log; +import android.widget.Toast; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; + +class ImportExportTask extends AsyncTask +{ + private static final String TAG = "BudgetWatch"; + + private static final String TARGET_FILE = "LoyaltyCardLocker.csv"; + + private Activity activity; + private boolean doImport; + private DataFormat format; + + private ProgressDialog progress; + + public ImportExportTask(Activity activity, boolean doImport, DataFormat format) + { + super(); + this.activity = activity; + this.doImport = doImport; + this.format = format; + } + + private void toastWithArg(int stringId, String argument) + { + final String template = activity.getResources().getString(stringId); + final String message = String.format(template, argument); + + activity.runOnUiThread(new Runnable() + { + @Override + public void run() + { + Toast.makeText(activity, message, Toast.LENGTH_LONG).show(); + } + }); + } + + private void performImport(File importFile, DBHelper db) + { + if(importFile.exists() == false) + { + toastWithArg(R.string.fileMissing, importFile.getAbsolutePath()); + return; + } + + boolean result = false; + + try + { + FileInputStream fileReader = new FileInputStream(importFile); + InputStreamReader reader = new InputStreamReader(fileReader, Charset.forName("UTF-8")); + result = MultiFormatImporter.importData(db, reader, format); + reader.close(); + } + catch(IOException e) + { + Log.e(TAG, "Unable to import file", e); + } + + int messageId = result ? R.string.importedFrom : R.string.importFailed; + toastWithArg(messageId, importFile.getAbsolutePath()); + } + + private void performExport(File exportFile, DBHelper db) + { + boolean result = false; + + try + { + FileOutputStream fileWriter = new FileOutputStream(exportFile); + OutputStreamWriter writer = new OutputStreamWriter(fileWriter, Charset.forName("UTF-8")); + result = MultiFormatExporter.exportData(db, writer, format); + writer.close(); + } + catch (IOException e) + { + Log.e(TAG, "Unable to export file", e); + } + + int messageId = result ? R.string.exportedTo : R.string.exportFailed; + toastWithArg(messageId, exportFile.getAbsolutePath()); + } + + protected void onPreExecute() + { + progress = new ProgressDialog(activity); + progress.setTitle(doImport ? R.string.importing : R.string.exporting); + + progress.setOnDismissListener(new DialogInterface.OnDismissListener() + { + @Override + public void onDismiss(DialogInterface dialog) + { + ImportExportTask.this.cancel(true); + } + }); + + progress.show(); + } + + protected Void doInBackground(Void... nothing) + { + final File sdcardDir = Environment.getExternalStorageDirectory(); + final File importExportFile = new File(sdcardDir, TARGET_FILE); + final DBHelper db = new DBHelper(activity); + + if(doImport) + { + performImport(importExportFile, db); + } + else + { + performExport(importExportFile, db); + } + + return null; + } + + protected void onPostExecute(Void result) + { + progress.dismiss(); + Log.i(TAG, (doImport ? "Import" : "Export") + " Complete"); + } + + protected void onCancelled() + { + progress.dismiss(); + Log.i(TAG, (doImport ? "Import" : "Export") + " Cancelled"); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c1de29597..6242a5c68 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -27,4 +27,16 @@ %1$s: %2$s %1$s - %2$s + + Import/Export + Import + Export + Data is imported to/exported from LoyaltyCardLocker.csv on external storage + Imported from: %1$s + Exported to: %1$s + File missing: %1$s + Failed to import: %1$s + Failed to export: %1$s + Importing… + Exporting… \ No newline at end of file diff --git a/app/src/test/java/protect/card_locker/ImportExportTest.java b/app/src/test/java/protect/card_locker/ImportExportTest.java index 5e1b69900..0950d4b59 100644 --- a/app/src/test/java/protect/card_locker/ImportExportTest.java +++ b/app/src/test/java/protect/card_locker/ImportExportTest.java @@ -204,4 +204,39 @@ public class ImportExportTest assertEquals(0, db.getLoyaltyCardCount()); } } + + @Test + public void useImportExportTask() + { + final int NUM_CARDS = 10; + + for(DataFormat format : DataFormat.values()) + { + addLoyaltyCards(NUM_CARDS); + + // Export to whatever the default location is + ImportExportTask task = new ImportExportTask(activity, false, format); + task.execute(); + + // Actually run the task to completion + Robolectric.flushBackgroundThreadScheduler(); + + clearDatabase(); + + // Import everything back from the default location + + task = new ImportExportTask(activity, true, format); + task.execute(); + + // Actually run the task to completion + Robolectric.flushBackgroundThreadScheduler(); + + assertEquals(NUM_CARDS, db.getLoyaltyCardCount()); + + checkLoyaltyCards(); + + // Clear the database for the next format under test + clearDatabase(); + } + } }