diff --git a/app/src/main/java/protect/card_locker/DBHelper.java b/app/src/main/java/protect/card_locker/DBHelper.java index 53ec2ea5ca..5b9626253e 100644 --- a/app/src/main/java/protect/card_locker/DBHelper.java +++ b/app/src/main/java/protect/card_locker/DBHelper.java @@ -16,7 +16,9 @@ import java.util.Arrays; import java.util.Currency; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class DBHelper extends SQLiteOpenHelper { public static final String DATABASE_NAME = "Catima.db"; @@ -323,6 +325,37 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } + public static void clearDatabase(final SQLiteDatabase db) { + db.execSQL("DELETE FROM " + LoyaltyCardDbGroups.TABLE); + db.execSQL("DELETE FROM " + LoyaltyCardDbIds.TABLE); + db.execSQL("DELETE FROM " + LoyaltyCardDbIdsGroups.TABLE); + } + + public static void clearImageFiles(Context context, final Set before, final Set after) { + Set deleted = new HashSet<>(before); + if (after != null) { + deleted.removeAll(after); + } + for (String name : deleted) { + context.deleteFile(name); + } + } + + public static Set imageFiles(Context context, final SQLiteDatabase database) { + Set files = new HashSet<>(); + Cursor cardCursor = getLoyaltyCardCursor(database); + while (cardCursor.moveToNext()) { + LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor); + for (ImageLocationType imageLocationType : ImageLocationType.values()) { + String name = Utils.getCardImageFileName(card.id, imageLocationType); + if (Utils.retrieveCardImageAsFile(context, name).exists()) { + files.add(name); + } + } + } + return files; + } + private static ContentValues generateFTSContentValues(final int id, final String store, final String note) { // FTS on Android is severely limited and can only search for word starting with a certain string // So for each word, we grab every single substring diff --git a/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java b/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java index 52d521781c..ab5fb3a8aa 100644 --- a/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java @@ -22,7 +22,9 @@ import java.util.ArrayList; import java.util.Currency; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; import protect.card_locker.CatimaBarcode; import protect.card_locker.DBHelper; @@ -39,7 +41,8 @@ * A header is expected for the each table showing the names of the columns. */ public class CatimaImporter implements Importer { - public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, InterruptedException { + public Set importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, InterruptedException { + Set imageFiles = new HashSet<>(); InputStream bufferedInputStream = new BufferedInputStream(input); bufferedInputStream.mark(100); @@ -57,6 +60,7 @@ public void importData(Context context, SQLiteDatabase database, InputStream inp importCSV(context, database, zipInputStream); } else if (fileName.endsWith(".png")) { Utils.saveCardImage(context, ZipUtils.readImage(zipInputStream), fileName); + imageFiles.add(fileName); } else { throw new FormatException("Unexpected file in import: " + fileName); } @@ -69,6 +73,8 @@ public void importData(Context context, SQLiteDatabase database, InputStream inp } input.close(); + + return imageFiles; } public void importCSV(Context context, SQLiteDatabase database, InputStream input) throws IOException, FormatException, InterruptedException { diff --git a/app/src/main/java/protect/card_locker/importexport/FidmeImporter.java b/app/src/main/java/protect/card_locker/importexport/FidmeImporter.java index b1e411a0f1..cbcd96a570 100644 --- a/app/src/main/java/protect/card_locker/importexport/FidmeImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/FidmeImporter.java @@ -17,6 +17,7 @@ import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.text.ParseException; +import java.util.Set; import protect.card_locker.CatimaBarcode; import protect.card_locker.DBHelper; @@ -31,7 +32,7 @@ * A header is expected for the each table showing the names of the columns. */ public class FidmeImporter implements Importer { - public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException { + public Set importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException { // We actually retrieve a .zip file ZipInputStream zipInputStream = new ZipInputStream(input, password); @@ -70,6 +71,8 @@ public void importData(Context context, SQLiteDatabase database, InputStream inp } zipInputStream.close(); + + return null; } /** diff --git a/app/src/main/java/protect/card_locker/importexport/Importer.java b/app/src/main/java/protect/card_locker/importexport/Importer.java index 41f73df262..e904f28dd6 100644 --- a/app/src/main/java/protect/card_locker/importexport/Importer.java +++ b/app/src/main/java/protect/card_locker/importexport/Importer.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.io.InputStream; import java.text.ParseException; +import java.util.Set; import protect.card_locker.FormatException; @@ -23,5 +24,5 @@ public interface Importer { * @throws IOException * @throws FormatException */ - void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, InterruptedException, JSONException, ParseException; + Set importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, InterruptedException, JSONException, ParseException; } diff --git a/app/src/main/java/protect/card_locker/importexport/MultiFormatImporter.java b/app/src/main/java/protect/card_locker/importexport/MultiFormatImporter.java index a5306dd336..9d5589b28a 100644 --- a/app/src/main/java/protect/card_locker/importexport/MultiFormatImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/MultiFormatImporter.java @@ -7,6 +7,9 @@ import net.lingala.zip4j.exception.ZipException; import java.io.InputStream; +import java.util.Set; + +import protect.card_locker.DBHelper; public class MultiFormatImporter { private static final String TAG = "Catima"; @@ -17,6 +20,8 @@ public class MultiFormatImporter { *

* The input stream is not closed, and doing so is the * responsibility of the caller. + *

+ * NB: this deletes all existing data! * * @return ImportExportResult.Success if the database was successfully imported, * or another result otherwise. If no Success, no data was written to @@ -43,9 +48,12 @@ public static ImportExportResult importData(Context context, SQLiteDatabase data String error = null; if (importer != null) { database.beginTransaction(); + Set imageFilesBefore = DBHelper.imageFiles(context, database); + DBHelper.clearDatabase(database); try { - importer.importData(context, database, input, password); + Set imageFilesAfter = importer.importData(context, database, input, password); database.setTransactionSuccessful(); + DBHelper.clearImageFiles(context, imageFilesBefore, imageFilesAfter); return new ImportExportResult(ImportExportResultType.Success); } catch (ZipException e) { if (e.getType().equals(ZipException.Type.WRONG_PASSWORD)) { diff --git a/app/src/main/java/protect/card_locker/importexport/StocardImporter.java b/app/src/main/java/protect/card_locker/importexport/StocardImporter.java index 1aa90e3e03..30d0fbf52f 100644 --- a/app/src/main/java/protect/card_locker/importexport/StocardImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/StocardImporter.java @@ -23,6 +23,8 @@ import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; import protect.card_locker.CatimaBarcode; import protect.card_locker.DBHelper; @@ -42,7 +44,8 @@ public class StocardImporter implements Importer { private static final String TAG = "Catima"; - public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException { + public Set importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException { + Set imageFiles = new HashSet<>(); HashMap> loyaltyCardHashMap = new HashMap<>(); HashMap> providers = new HashMap<>(); @@ -233,18 +236,26 @@ public void importData(Context context, SQLiteDatabase database, InputStream inp long loyaltyCardInternalId = DBHelper.insertLoyaltyCard(database, store, note, null, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, 0, null,0); if (cardIcon != null) { - Utils.saveCardImage(context, cardIcon, (int) loyaltyCardInternalId, ImageLocationType.icon); + String fileName = Utils.getCardImageFileName((int) loyaltyCardInternalId, ImageLocationType.icon); + Utils.saveCardImage(context, cardIcon, fileName); + imageFiles.add(fileName); } if (loyaltyCardData.containsKey("frontImage")) { - Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("frontImage"), (int) loyaltyCardInternalId, ImageLocationType.front); + String fileName = Utils.getCardImageFileName((int) loyaltyCardInternalId, ImageLocationType.front); + Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("frontImage"), fileName); + imageFiles.add(fileName); } if (loyaltyCardData.containsKey("backImage")) { - Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("backImage"), (int) loyaltyCardInternalId, ImageLocationType.back); + String fileName = Utils.getCardImageFileName((int) loyaltyCardInternalId, ImageLocationType.back); + Utils.saveCardImage(context, (Bitmap) loyaltyCardData.get("backImage"), fileName); + imageFiles.add(fileName); } } zipInputStream.close(); + + return imageFiles; } private boolean startsWith(String[] full, String[] start, int minExtraLength) { diff --git a/app/src/main/java/protect/card_locker/importexport/VoucherVaultImporter.java b/app/src/main/java/protect/card_locker/importexport/VoucherVaultImporter.java index b0d1033664..0272ade43b 100644 --- a/app/src/main/java/protect/card_locker/importexport/VoucherVaultImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/VoucherVaultImporter.java @@ -21,6 +21,7 @@ import java.text.SimpleDateFormat; import java.util.Currency; import java.util.Date; +import java.util.Set; import java.util.TimeZone; import protect.card_locker.CatimaBarcode; @@ -36,7 +37,7 @@ * A header is expected for the each table showing the names of the columns. */ public class VoucherVaultImporter implements Importer { - public void importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException { + public Set importData(Context context, SQLiteDatabase database, InputStream input, char[] password) throws IOException, FormatException, JSONException, ParseException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); StringBuilder sb = new StringBuilder(); @@ -130,5 +131,7 @@ public void importData(Context context, SQLiteDatabase database, InputStream inp } bufferedReader.close(); + + return null; } } \ No newline at end of file diff --git a/app/src/main/res/layout/import_export_activity.xml b/app/src/main/res/layout/import_export_activity.xml index 384764242b..84fcc57a92 100644 --- a/app/src/main/res/layout/import_export_activity.xml +++ b/app/src/main/res/layout/import_export_activity.xml @@ -89,6 +89,14 @@ android:textSize="@dimen/text_size_medium" android:text="@string/importOptionFilesystemExplanation"/> + +