availableImageTypes = new ArrayList<>();
+
+ if (isBarcodeSupported) {
+ availableImageTypes.add(LoyaltyCardImageType.BARCODE);
+ }
+
+ frontImageBitmap = loyaltyCard.getImageFront(this);
+ if (frontImageBitmap != null) {
+ availableImageTypes.add(LoyaltyCardImageType.IMAGE_FRONT);
+ }
+
+ backImageBitmap = loyaltyCard.getImageBack(this);
+ if (backImageBitmap != null) {
+ availableImageTypes.add(LoyaltyCardImageType.IMAGE_BACK);
+ }
+
+ // Card edits may remove barcode/front/back images, so keep the previously selected index in range.
+ int initialIndex = cardNavigator.isEmpty()
+ ? (restoredImageIndex != null ? restoredImageIndex : 0)
+ : cardNavigator.getCurrentIndex();
+ LoyaltyCardImageNavigator navigator =
+ new LoyaltyCardImageNavigator(availableImageTypes, initialIndex);
+ restoredImageIndex = null;
+ return navigator;
+ }
+
+ private void renderCurrentMainImage(boolean waitForResize) {
+ mainImageRenderer.renderCurrent(
+ cardNavigator.getCurrent(),
+ frontImageBitmap,
+ backImageBitmap,
+ format,
+ barcodeEncoding,
+ cardIdString,
+ barcodeIdString,
+ barcodeRenderTarget,
+ binding.mainImageDescription,
+ binding.mainCardView,
+ isFullscreen,
+ waitForResize
+ );
+ }
+
+ private void syncFullscreenScalers() {
+ binding.barcodeScaler.setProgress(loyaltyCard.zoomLevel);
+ setScalerGuideline(loyaltyCard.zoomLevel);
+ binding.barcodeWidthscaler.setProgress(loyaltyCard.zoomLevelWidth);
+ setScalerWidthGuideline(loyaltyCard.zoomLevelWidth);
}
@SuppressWarnings("deprecation")
private void showWhenLockedSdkLessThan27(Window window) {
+ // Pre-O_MR1 devices still need the legacy window flags because setShowWhenLocked(true) is unavailable.
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
@@ -859,13 +727,11 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
return super.onCreateOptionsMenu(menu);
}
-
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (loyaltyCard != null) {
- // Update star status
if (loyaltyCard.starStatus == 1) {
menu.findItem(R.id.action_star_unstar).setIcon(R.drawable.ic_starred);
menu.findItem(R.id.action_star_unstar).setTitle(R.string.unstar);
@@ -874,7 +740,6 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
menu.findItem(R.id.action_star_unstar).setTitle(R.string.star);
}
- // Update archive/unarchive button
if (loyaltyCard.archiveStatus != 0) {
menu.findItem(R.id.action_unarchive).setVisible(true);
menu.findItem(R.id.action_archive).setVisible(false);
@@ -967,10 +832,9 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
private void showHideElementsForScreenSize() {
int orientation = getResources().getConfiguration().orientation;
- // Detect square-ish screens like the Unihertz Titan
+ // Treat square-ish devices such as the Unihertz Titan like landscape to avoid a cramped header layout.
boolean isSmallHeight = getResources().getDisplayMetrics().heightPixels < (getResources().getDisplayMetrics().widthPixels * 1.5);
- // Treat sqaure-ish screens as
if (orientation == Configuration.ORIENTATION_LANDSCAPE || isSmallHeight) {
Log.d(TAG, "Detected landscape mode or square-ish screen");
binding.iconContainer.setVisibility(View.GONE);
@@ -982,144 +846,53 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
enableToolbarBackButton();
}
- private void drawBarcode(boolean addPadding) {
- mTasks.flushTaskList(TaskHandler.TYPE.BARCODE, true, false, false);
-
- if (format != null) {
- BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(
- getApplicationContext(),
- barcodeRenderTarget,
- barcodeIdString != null ? barcodeIdString : cardIdString,
- format,
- barcodeEncoding,
- null,
- false,
- this,
- addPadding,
- isFullscreen);
- mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
- }
- }
-
- private void redrawBarcodeAfterResize(boolean addPadding) {
- if (format != null) {
- barcodeRenderTarget.getViewTreeObserver().addOnGlobalLayoutListener(
- new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- barcodeRenderTarget.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-
- Log.d(TAG, "ImageView size now known");
- drawBarcode(addPadding);
- }
- });
- }
- }
-
- private void drawMainImage(int index, boolean waitForResize, boolean isFullscreen) {
- if (imageTypes.isEmpty()) {
- barcodeRenderTarget.setVisibility(View.GONE);
- binding.mainCardView.setCardBackgroundColor(Color.TRANSPARENT);
- binding.mainImageDescription.setTextColor(MaterialColors.getColor(binding.mainImageDescription, com.google.android.material.R.attr.colorOnSurfaceVariant));
-
- binding.mainImageDescription.setText(loyaltyCard.cardId);
- return;
- }
-
- ImageType wantedImageType = imageTypes.get(index);
-
- if (wantedImageType == ImageType.BARCODE) {
- barcodeRenderTarget.setBackgroundColor(Color.WHITE);
- binding.mainCardView.setCardBackgroundColor(Color.WHITE);
- binding.mainImageDescription.setTextColor(getResources().getColor(R.color.md_theme_light_onSurfaceVariant));
-
- if (waitForResize) {
- redrawBarcodeAfterResize(!isFullscreen);
- } else {
- drawBarcode(!isFullscreen);
- }
-
- binding.mainImageDescription.setText(loyaltyCard.cardId);
- barcodeRenderTarget.setContentDescription(getString(R.string.barcodeImageDescriptionWithType, format.prettyName()));
- } else if (wantedImageType == ImageType.IMAGE_FRONT) {
- barcodeRenderTarget.setImageBitmap(frontImageBitmap);
- barcodeRenderTarget.setBackgroundColor(Color.TRANSPARENT);
- binding.mainCardView.setCardBackgroundColor(Color.TRANSPARENT);
- binding.mainImageDescription.setTextColor(MaterialColors.getColor(binding.mainImageDescription, com.google.android.material.R.attr.colorOnSurfaceVariant));
-
- binding.mainImageDescription.setText(getString(R.string.frontImageDescription));
- barcodeRenderTarget.setContentDescription(getString(R.string.frontImageDescription));
- } else if (wantedImageType == ImageType.IMAGE_BACK) {
- barcodeRenderTarget.setImageBitmap(backImageBitmap);
- barcodeRenderTarget.setBackgroundColor(Color.TRANSPARENT);
- binding.mainCardView.setCardBackgroundColor(Color.TRANSPARENT);
- binding.mainImageDescription.setTextColor(MaterialColors.getColor(binding.mainImageDescription, com.google.android.material.R.attr.colorOnSurfaceVariant));
-
- binding.mainImageDescription.setText(getString(R.string.backImageDescription));
- barcodeRenderTarget.setContentDescription(getString(R.string.backImageDescription));
- } else {
- throw new IllegalArgumentException("Unknown image type: " + wantedImageType);
- }
-
- barcodeRenderTarget.setVisibility(View.VISIBLE);
- }
-
private void setMainImage(boolean next, boolean overflow) {
- int newIndex = mainImageIndex + (next ? 1 : -1);
-
- if (newIndex >= imageTypes.size() && overflow) {
- newIndex = 0;
- }
-
- if (newIndex == -1 || newIndex >= imageTypes.size()) {
+ boolean moved = next ? cardNavigator.moveNext(overflow) : cardNavigator.movePrevious();
+ if (!moved) {
return;
}
- mainImageIndex = newIndex;
+ renderCurrentMainImage(false);
- drawMainImage(newIndex, false, isFullscreen);
-
- setMainImagePreviousNextButtons();
- setMainImageAccessibility();
+ updateMainImageUiState();
}
- private void setMainImageAccessibility() {
- // Single-click actions
- if (mainImageIndex == 0) {
- ViewCompat.replaceAccessibilityAction(
- binding.mainImage,
- AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
- getString(R.string.moveBarcodeToTopOfScreen),
- null
- );
- } else {
- int accessibilityClickAction;
- if (mainImageIndex == 1) {
- accessibilityClickAction = R.string.openFrontImageInGalleryApp;
- } else if (mainImageIndex == 2) {
- accessibilityClickAction = R.string.openBackImageInGalleryApp;
- } else {
- throw new IndexOutOfBoundsException("setMainImageAccessibility was out of range (action_click)");
- }
+ private boolean isShowingCardIdDescription() {
+ return cardNavigator.isEmpty() || cardNavigator.getCurrent() == LoyaltyCardImageType.BARCODE;
+ }
- ViewCompat.replaceAccessibilityAction(
- binding.mainImage,
- AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
- getString(accessibilityClickAction),
- null
- );
+ private void updateMainImageUiState() {
+ updateMainImagePreviousNextButtons();
+ updateMainImageAccessibility();
+ }
+
+ private void updateMainImageAccessibility() {
+ // The same image view can represent barcode/front/back states, so accessibility actions must track that role.
+ int accessibilityClickAction;
+ LoyaltyCardImageType currentImageType = cardNavigator.getCurrent();
+ if (currentImageType == LoyaltyCardImageType.IMAGE_FRONT) {
+ accessibilityClickAction = R.string.openFrontImageInGalleryApp;
+ } else if (currentImageType == LoyaltyCardImageType.IMAGE_BACK) {
+ accessibilityClickAction = R.string.openBackImageInGalleryApp;
+ } else {
+ accessibilityClickAction = R.string.moveBarcodeToTopOfScreen;
}
- // Long-press actions
+ ViewCompat.replaceAccessibilityAction(
+ binding.mainImage,
+ AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
+ getString(accessibilityClickAction),
+ null
+ );
+
int accessibilityLongPressAction;
- if (mainImageIndex == 0) {
+ LoyaltyCardImageType nextImageType = cardNavigator.peekNext(true);
+ if (nextImageType == LoyaltyCardImageType.IMAGE_FRONT) {
accessibilityLongPressAction = R.string.switchToFrontImage;
- } else if (mainImageIndex == 1) {
+ } else if (nextImageType == LoyaltyCardImageType.IMAGE_BACK) {
accessibilityLongPressAction = R.string.switchToBackImage;
- } else if (mainImageIndex == 2) {
- accessibilityLongPressAction = R.string.switchToBarcode;
} else {
- throw new IndexOutOfBoundsException("setMainImageAccessibility was out of range (action_long_click)");
+ accessibilityLongPressAction = R.string.switchToBarcode;
}
ViewCompat.replaceAccessibilityAction(
@@ -1130,45 +903,35 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
);
}
- private void setMainImagePreviousNextButtons() {
- // Ensure the main image index is valid. After a card update, some images (front/back/barcode)
- // may have been removed, so the index should not exceed the number of available images.
- if(mainImageIndex > imageTypes.size() - 1){
- mainImageIndex = 0;
- }
-
- if (imageTypes.size() < 2) {
+ private void updateMainImagePreviousNextButtons() {
+ if (cardNavigator.size() < 2) {
binding.mainLeftButton.setVisibility(View.INVISIBLE);
binding.mainRightButton.setVisibility(View.INVISIBLE);
-
binding.mainLeftButton.setOnClickListener(null);
binding.mainRightButton.setOnClickListener(null);
-
return;
}
- final ImageButton prevButton;
+ final ImageButton previousButton;
final ImageButton nextButton;
-
+ // In RTL, the visual left/right buttons map to opposite logical navigation directions.
if (getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- prevButton = binding.mainRightButton;
+ previousButton = binding.mainRightButton;
nextButton = binding.mainLeftButton;
} else {
- prevButton = binding.mainLeftButton;
+ previousButton = binding.mainLeftButton;
nextButton = binding.mainRightButton;
}
- // Enable left button if we can go further left
- if (mainImageIndex > 0) {
- prevButton.setVisibility(View.VISIBLE);
- prevButton.setOnClickListener(view -> setMainImage(false, false));
+ if (cardNavigator.canGoPrevious()) {
+ previousButton.setVisibility(View.VISIBLE);
+ previousButton.setOnClickListener(view -> setMainImage(false, false));
} else {
- prevButton.setVisibility(View.INVISIBLE);
- prevButton.setOnClickListener(null);
+ previousButton.setVisibility(View.INVISIBLE);
+ previousButton.setOnClickListener(null);
}
- // Enable right button if we can go further right
- if (mainImageIndex < (imageTypes.size() - 1)) {
+ if (cardNavigator.canGoNext()) {
nextButton.setVisibility(View.VISIBLE);
nextButton.setOnClickListener(view -> setMainImage(true, false));
} else {
@@ -1178,124 +941,99 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
}
/**
- * When enabled, hides the status bar and moves the barcode to the top of the screen.
- *
- * The purpose of this function is to make sure the barcode can be scanned from the phone
- * by machines which offer no space to insert the complete device.
+ * Fullscreen hides system chrome and moves the barcode higher on screen so scanners can read
+ * it even when the whole device does not fit cleanly in front of the reader.
*/
private void setFullscreen(boolean enabled) {
- ActionBar actionBar = getSupportActionBar();
isFullscreen = enabled;
+ ActionBar actionBar = getSupportActionBar();
- if (enabled && !imageTypes.isEmpty()) {
- Log.d(TAG, "Move into fullscreen");
-
+ if (enabled && !cardNavigator.isEmpty()) {
barcodeRenderTarget = binding.fullscreenImage;
-
- // Show only fullscreen view
binding.container.setVisibility(View.GONE);
binding.fullscreenLayout.setVisibility(View.VISIBLE);
+ // Square barcodes resize uniformly, and Data Matrix behaves similarly, so width-only scaling adds no value.
+ binding.setWidthLayout.setVisibility(
+ format == null || format.isSquare() || format.format() == com.google.zxing.BarcodeFormat.DATA_MATRIX
+ ? View.GONE
+ : View.VISIBLE
+ );
+ renderCurrentMainImage(true);
+ syncFullscreenScalers();
- // Only show width slider if the barcode isn't square (square barcodes will resize height and width together)
- // or if the internals of the barcode are squares, like DATA_MATRIX
- binding.setWidthLayout.setVisibility((format.isSquare() || format.format() == BarcodeFormat.DATA_MATRIX) ? View.GONE : View.VISIBLE);
-
- drawMainImage(mainImageIndex, true, isFullscreen);
-
- binding.barcodeScaler.setProgress(loyaltyCard.zoomLevel);
- setScalerGuideline(loyaltyCard.zoomLevel);
-
- binding.barcodeWidthscaler.setProgress(loyaltyCard.zoomLevelWidth);
- setScalerWidthGuideline(loyaltyCard.zoomLevelWidth);
-
- // Hide actionbar
if (actionBar != null) {
actionBar.hide();
}
- // Hide other UI elements
binding.bottomAppBar.setVisibility(View.GONE);
binding.fabEdit.setVisibility(View.GONE);
-
- // Set Android to fullscreen mode
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- Window window = getWindow();
- if (window != null) {
- window.setDecorFitsSystemWindows(false);
- WindowInsetsController wic = window.getInsetsController();
- if (wic != null) {
- wic.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
- wic.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
- }
- }
- } else {
- setFullscreenModeSdkLessThan30();
- }
+ setFullscreenMode();
} else {
- Log.d(TAG, "Move out of fullscreen");
-
barcodeRenderTarget = binding.mainImage;
-
- // Show only regular view
binding.container.setVisibility(View.VISIBLE);
binding.fullscreenLayout.setVisibility(View.GONE);
+ renderCurrentMainImage(true);
- drawMainImage(mainImageIndex, true, isFullscreen);
-
- // Show actionbar
if (actionBar != null) {
actionBar.show();
}
- // Show other UI elements
binding.bottomAppBar.setVisibility(View.VISIBLE);
binding.fabEdit.setVisibility(View.VISIBLE);
-
- // Unset fullscreen mode
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- Window window = getWindow();
- if (window != null) {
- window.setDecorFitsSystemWindows(true);
- WindowInsetsController wic = window.getInsetsController();
- if (wic != null) {
- wic.show(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
- wic.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_DEFAULT);
- }
- }
- } else {
- unsetFullscreenModeSdkLessThan30();
- }
+ unsetFullscreenMode();
}
-
Log.d("setFullScreen", "Is full screen enabled? " + enabled + " Zoom Level = " + binding.barcodeScaler.getProgress());
}
@SuppressWarnings("deprecation")
- private void unsetFullscreenModeSdkLessThan30() {
+ private void setFullscreenMode() {
Window window = getWindow();
- if (window != null) {
- window.getDecorView().setSystemUiVisibility(
- window.getDecorView().getSystemUiVisibility()
- & ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- & ~View.SYSTEM_UI_FLAG_FULLSCREEN
- );
+ if (window == null) {
+ return;
}
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ window.setDecorFitsSystemWindows(false);
+ WindowInsetsController wic = window.getInsetsController();
+ if (wic != null) {
+ wic.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
+ wic.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
+ }
+ return;
+ }
+
+ window.getDecorView().setSystemUiVisibility(
+ window.getDecorView().getSystemUiVisibility()
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ | View.SYSTEM_UI_FLAG_FULLSCREEN
+ );
}
@SuppressWarnings("deprecation")
- private void setFullscreenModeSdkLessThan30() {
+ private void unsetFullscreenMode() {
Window window = getWindow();
- if (window != null) {
- window.getDecorView().setSystemUiVisibility(
- window.getDecorView().getSystemUiVisibility()
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- | View.SYSTEM_UI_FLAG_FULLSCREEN
- );
+ if (window == null) {
+ return;
}
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ window.setDecorFitsSystemWindows(true);
+ WindowInsetsController wic = window.getInsetsController();
+ if (wic != null) {
+ wic.show(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
+ wic.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_DEFAULT);
+ }
+ return;
+ }
+
+ window.getDecorView().setSystemUiVisibility(
+ window.getDecorView().getSystemUiVisibility()
+ & ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ & ~View.SYSTEM_UI_FLAG_FULLSCREEN
+ );
}
private void copyCardIdToClipboard() {
- // Take the value that’s already displayed to the user
String value = loyaltyCard.cardId;
if (value == null || value.isEmpty()) {
diff --git a/app/src/main/java/protect/card_locker/cardview/LoyaltyCardViewDialogs.java b/app/src/main/java/protect/card_locker/cardview/LoyaltyCardViewDialogs.java
new file mode 100644
index 000000000..2c7daf68f
--- /dev/null
+++ b/app/src/main/java/protect/card_locker/cardview/LoyaltyCardViewDialogs.java
@@ -0,0 +1,246 @@
+package protect.card_locker.cardview;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.text.InputType;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.method.DigitsKeyListener;
+import android.text.style.ForegroundColorSpan;
+import android.text.util.Linkify;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.StringRes;
+import androidx.appcompat.app.AlertDialog;
+
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import com.google.android.material.textfield.TextInputEditText;
+
+import java.math.BigDecimal;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.function.Predicate;
+
+import protect.card_locker.*;
+
+final class LoyaltyCardViewDialogs {
+ interface BalanceUpdateListener {
+ void onBalanceUpdated(BigDecimal newBalance);
+ }
+
+ void showInfoDialog(Context context, LoyaltyCard loyaltyCard, List loyaltyCardGroups) {
+ AlertDialog.Builder infoDialog = new MaterialAlertDialogBuilder(context);
+
+ int dialogContentPadding = context.getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_padding);
+ infoDialog.setTitle(loyaltyCard.store);
+
+ TextView infoTextview = new TextView(context);
+ infoTextview.setPadding(
+ dialogContentPadding,
+ dialogContentPadding / 2,
+ dialogContentPadding,
+ 0
+ );
+ infoTextview.setAutoLinkMask(Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS | Linkify.WEB_URLS);
+ infoTextview.setTextIsSelectable(true);
+
+ SpannableStringBuilder infoText = new SpannableStringBuilder();
+ if (!loyaltyCard.note.isEmpty()) {
+ infoText.append(loyaltyCard.note);
+ }
+
+ if (!loyaltyCardGroups.isEmpty()) {
+ List groupNames = new ArrayList<>();
+ for (Group group : loyaltyCardGroups) {
+ groupNames.add(group._id);
+ }
+
+ padSpannableString(infoText);
+ infoText.append(context.getString(R.string.groupsList, TextUtils.join(", ", groupNames)));
+ }
+
+ if (hasBalance(loyaltyCard)) {
+ padSpannableString(infoText);
+ infoText.append(context.getString(
+ R.string.balanceSentence,
+ Utils.formatBalance(context, loyaltyCard.balance, loyaltyCard.balanceType)
+ ));
+ }
+
+ appendDateInfo(
+ context,
+ infoText,
+ loyaltyCard.validFrom,
+ Utils::isNotYetValid,
+ R.string.validFromSentence,
+ R.string.validFromSentence
+ );
+ appendDateInfo(
+ context,
+ infoText,
+ loyaltyCard.expiry,
+ Utils::hasExpired,
+ R.string.expiryStateSentenceExpired,
+ R.string.expiryStateSentence
+ );
+
+ infoTextview.setText(infoText);
+ infoDialog.setView(infoTextview);
+ infoDialog.setPositiveButton(R.string.ok, (dialogInterface, i) -> dialogInterface.dismiss());
+ infoDialog.create().show();
+ }
+
+ void showBalanceUpdateDialog(
+ Context context,
+ LoyaltyCard loyaltyCard,
+ BalanceUpdateListener balanceUpdateListener
+ ) {
+ AlertDialog.Builder builder = new MaterialAlertDialogBuilder(context);
+ builder.setTitle(R.string.updateBalanceTitle);
+
+ FrameLayout container = new FrameLayout(context);
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ );
+ int contentPadding = context.getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_padding);
+ params.leftMargin = contentPadding;
+ params.topMargin = contentPadding / 2;
+ params.rightMargin = contentPadding;
+
+ LinearLayout layout = new LinearLayout(context);
+ layout.setOrientation(LinearLayout.VERTICAL);
+
+ TextView currentTextview = new TextView(context);
+ currentTextview.setText(context.getString(
+ R.string.currentBalanceSentence,
+ Utils.formatBalance(context, loyaltyCard.balance, loyaltyCard.balanceType)
+ ));
+ layout.addView(currentTextview);
+
+ final TextInputEditText input = new TextInputEditText(context);
+ input.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
+ input.setKeyListener(DigitsKeyListener.getInstance("0123456789,."));
+ input.setHint(R.string.updateBalanceHint);
+
+ layout.addView(input);
+ layout.setLayoutParams(params);
+ container.addView(layout);
+ builder.setView(container);
+
+ builder.setPositiveButton(R.string.spend, (dialogInterface, i) -> {
+ try {
+ BigDecimal balanceChange = Utils.parseBalance(input.getText().toString(), loyaltyCard.balanceType);
+ BigDecimal newBalance = loyaltyCard.balance.subtract(balanceChange).max(new BigDecimal(0));
+ balanceUpdateListener.onBalanceUpdated(newBalance);
+ Toast.makeText(
+ context,
+ context.getString(
+ R.string.newBalanceSentence,
+ Utils.formatBalance(context, newBalance, loyaltyCard.balanceType)
+ ),
+ Toast.LENGTH_LONG
+ ).show();
+ } catch (ParseException e) {
+ Toast.makeText(context, R.string.amountParsingFailed, Toast.LENGTH_LONG).show();
+ }
+ });
+ builder.setNegativeButton(R.string.receive, (dialogInterface, i) -> {
+ try {
+ BigDecimal balanceChange = Utils.parseBalance(input.getText().toString(), loyaltyCard.balanceType);
+ BigDecimal newBalance = loyaltyCard.balance.add(balanceChange);
+ balanceUpdateListener.onBalanceUpdated(newBalance);
+ Toast.makeText(
+ context,
+ context.getString(
+ R.string.newBalanceSentence,
+ Utils.formatBalance(context, newBalance, loyaltyCard.balanceType)
+ ),
+ Toast.LENGTH_LONG
+ ).show();
+ } catch (ParseException e) {
+ Toast.makeText(context, R.string.amountParsingFailed, Toast.LENGTH_LONG).show();
+ }
+ });
+ builder.setNeutralButton(context.getString(R.string.cancel), (dialog, which) -> dialog.cancel());
+ AlertDialog dialog = builder.create();
+
+ // Button state depends on the parsed input, so listeners must be bound after the dialog exists.
+ input.addTextChangedListener(new SimpleTextWatcher() {
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ BigDecimal balanceChange;
+
+ try {
+ balanceChange = Utils.parseBalance(s.toString(), loyaltyCard.balanceType);
+ } catch (ParseException e) {
+ input.setError(context.getString(R.string.amountParsingFailed));
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
+ dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(false);
+ return;
+ }
+
+ input.setError(null);
+ boolean hasNonZeroValue = !balanceChange.equals(new BigDecimal(0));
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(hasNonZeroValue);
+ dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(hasNonZeroValue);
+ }
+ });
+
+ dialog.show();
+ // Touching dialog buttons before show() can crash because they are not created yet.
+ dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
+ dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(false);
+
+ if (dialog.getWindow() != null) {
+ dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+ }
+ // Focus immediately so the keyboard opens on the amount field.
+ input.requestFocus();
+ }
+
+ private boolean hasBalance(LoyaltyCard loyaltyCard) {
+ return !loyaltyCard.balance.equals(new BigDecimal(0));
+ }
+
+ private SpannableStringBuilder padSpannableString(SpannableStringBuilder spannableStringBuilder) {
+ if (spannableStringBuilder.length() > 0) {
+ spannableStringBuilder.append("\n\n");
+ }
+
+ return spannableStringBuilder;
+ }
+
+ private void appendDateInfo(
+ Context context,
+ SpannableStringBuilder infoText,
+ Date date,
+ Predicate dateCheck,
+ @StringRes int dateCheckTrueString,
+ @StringRes int dateCheckFalseString
+ ) {
+ if (date == null) {
+ return;
+ }
+
+ String formattedDate = DateFormat.getDateInstance(DateFormat.LONG).format(date);
+
+ padSpannableString(infoText);
+ if (dateCheck.test(date)) {
+ int start = infoText.length();
+ infoText.append(context.getString(dateCheckTrueString, formattedDate));
+ infoText.setSpan(new ForegroundColorSpan(Color.RED), start, infoText.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ } else {
+ infoText.append(context.getString(dateCheckFalseString, formattedDate));
+ }
+ }
+}
diff --git a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java
index 0b7cbf9a8..d43d78893 100644
--- a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java
+++ b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java
@@ -51,6 +51,7 @@ import com.google.android.material.textfield.TextInputLayout;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.android.Intents;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -71,13 +72,19 @@ import java.text.DateFormat;
import java.text.ParseException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
import java.util.Currency;
import java.util.Date;
+import java.util.List;
+
+import protect.card_locker.cardview.LoyaltyCardViewActivity;
@RunWith(RobolectricTestRunner.class)
public class LoyaltyCardViewActivityTest {
private final String BARCODE_DATA = "428311627547";
private final CatimaBarcode BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A);
+ private final List> activityControllers = new ArrayList<>();
+ private final List dbHelpers = new ArrayList<>();
private final String EAN_BARCODE_DATA = "4763705295336";
private final CatimaBarcode EAN_BARCODE_TYPE = CatimaBarcode.fromBarcode(BarcodeFormat.EAN_13);
@@ -101,6 +108,30 @@ public class LoyaltyCardViewActivityTest {
ShadowLog.stream = System.out;
}
+ @After
+ public void tearDown() {
+ for (int index = activityControllers.size() - 1; index >= 0; index--) {
+ ActivityController extends Activity> activityController = activityControllers.get(index);
+ try {
+ activityController.pause().stop().destroy();
+ } catch (RuntimeException ignored) {
+ try {
+ activityController.destroy();
+ } catch (RuntimeException ignoredAgain) {
+ }
+ }
+ }
+ activityControllers.clear();
+
+ for (int index = dbHelpers.size() - 1; index >= 0; index--) {
+ try {
+ dbHelpers.get(index).close();
+ } catch (RuntimeException ignored) {
+ }
+ }
+ dbHelpers.clear();
+ }
+
/**
* Register a handler in the package manager for a image capture intent
*/
@@ -137,87 +168,110 @@ public class LoyaltyCardViewActivityTest {
final String barcodeType,
final String barcodeEncoding,
boolean creatingNewCard) throws ParseException {
- SQLiteDatabase database = new DBHelper(activity).getWritableDatabase();
- if (creatingNewCard) {
- assertEquals(0, DBHelper.getLoyaltyCardCount(database));
- } else {
+ DBHelper dbHelper = new DBHelper(activity);
+ SQLiteDatabase database = dbHelper.getWritableDatabase();
+ try {
+ if (creatingNewCard) {
+ assertEquals(0, DBHelper.getLoyaltyCardCount(database));
+ } else {
+ assertEquals(1, DBHelper.getLoyaltyCardCount(database));
+ }
+
+ final EditText storeField = activity.findViewById(R.id.storeNameEdit);
+ final EditText noteField = activity.findViewById(R.id.noteEdit);
+ final TextInputLayout validFromView = activity.findViewById(R.id.validFromView);
+ final TextInputLayout expiryView = activity.findViewById(R.id.expiryView);
+ final EditText balanceView = activity.findViewById(R.id.balanceField);
+ final EditText balanceCurrencyField = activity.findViewById(R.id.balanceCurrencyField);
+ final TextView cardIdField = activity.findViewById(R.id.cardIdView);
+ final TextView barcodeIdField = activity.findViewById(R.id.barcodeIdField);
+ final TextView barcodeTypeField = activity.findViewById(R.id.barcodeTypeField);
+ final TextView barcodeEncodingField = activity.findViewById(R.id.barcodeEncodingField);
+
+ storeField.setText(store);
+ noteField.setText(note);
+ validFromView.setTag(validFrom);
+ expiryView.setTag(expiry);
+ balanceView.setText(balance.toPlainString());
+ balanceCurrencyField.setText(balanceType);
+ cardIdField.setText(cardId);
+ barcodeIdField.setText(barcodeId);
+ barcodeTypeField.setText(barcodeType);
+ barcodeEncodingField.setText(barcodeEncoding);
+
+ assertEquals(false, activity.isFinishing());
+ activity.findViewById(R.id.fabSave).performClick();
+ assertEquals(true, activity.isFinishing());
+
assertEquals(1, DBHelper.getLoyaltyCardCount(database));
+
+ LoyaltyCard card = DBHelper.getLoyaltyCard(activity.getApplicationContext(), database, 1);
+ assertEquals(store, card.store);
+ assertEquals(note, card.note);
+ assertEquals(balance, card.balance);
+
+ // The special "Any date" string shouldn't actually be written to the loyalty card
+ if (validFrom.equals(activity.getApplicationContext().getString(R.string.anyDate))) {
+ assertEquals(null, card.validFrom);
+ } else {
+ assertEquals(DateFormat.getDateInstance().parse(validFrom), card.validFrom);
+ }
+
+ // The special "Never" string shouldn't actually be written to the loyalty card
+ if (expiry.equals(activity.getApplicationContext().getString(R.string.never))) {
+ assertEquals(null, card.expiry);
+ } else {
+ assertEquals(DateFormat.getDateInstance().parse(expiry), card.expiry);
+ }
+
+ // The special "Points" string shouldn't actually be written to the loyalty card
+ if (balanceType.equals(activity.getApplicationContext().getString(R.string.points))) {
+ assertEquals(null, card.balanceType);
+ } else {
+ assertEquals(Currency.getInstance(balanceType), card.balanceType);
+ }
+ assertEquals(cardId, card.cardId);
+
+ // The special "Same as barcode ID" string shouldn't actually be written to the loyalty card
+ if (barcodeId.equals(activity.getApplicationContext().getString(R.string.sameAsCardId))) {
+ assertEquals(null, card.barcodeId);
+ } else {
+ assertEquals(barcodeId, card.barcodeId);
+ }
+
+ // The special "No barcode" string shouldn't actually be written to the loyalty card
+ if (barcodeType.equals(activity.getApplicationContext().getString(R.string.noBarcode))) {
+ assertEquals(null, card.barcodeType);
+ } else {
+ assertEquals(CatimaBarcode.fromName(barcodeType).format(), card.barcodeType.format());
+ }
+
+ assertEquals(Charset.forName(barcodeEncoding), card.barcodeEncoding);
+
+ assertNotNull(card.headerColor);
+ } finally {
+ dbHelper.close();
}
+ }
- final EditText storeField = activity.findViewById(R.id.storeNameEdit);
- final EditText noteField = activity.findViewById(R.id.noteEdit);
- final TextInputLayout validFromView = activity.findViewById(R.id.validFromView);
- final TextInputLayout expiryView = activity.findViewById(R.id.expiryView);
- final EditText balanceView = activity.findViewById(R.id.balanceField);
- final EditText balanceCurrencyField = activity.findViewById(R.id.balanceCurrencyField);
- final TextView cardIdField = activity.findViewById(R.id.cardIdView);
- final TextView barcodeIdField = activity.findViewById(R.id.barcodeIdField);
- final TextView barcodeTypeField = activity.findViewById(R.id.barcodeTypeField);
- final TextView barcodeEncodingField = activity.findViewById(R.id.barcodeEncodingField);
+ private SQLiteDatabase getWritableEmptyDatabase(Context context) {
+ DBHelper dbHelper = TestHelpers.getEmptyDb(context);
+ dbHelpers.add(dbHelper);
+ return dbHelper.getWritableDatabase();
+ }
- storeField.setText(store);
- noteField.setText(note);
- validFromView.setTag(validFrom);
- expiryView.setTag(expiry);
- balanceView.setText(balance.toPlainString());
- balanceCurrencyField.setText(balanceType);
- cardIdField.setText(cardId);
- barcodeIdField.setText(barcodeId);
- barcodeTypeField.setText(barcodeType);
- barcodeEncodingField.setText(barcodeEncoding);
+ private ActivityController trackActivityController(ActivityController activityController) {
+ activityControllers.add(activityController);
+ return activityController;
+ }
- assertEquals(false, activity.isFinishing());
- activity.findViewById(R.id.fabSave).performClick();
- assertEquals(true, activity.isFinishing());
-
- assertEquals(1, DBHelper.getLoyaltyCardCount(database));
-
- LoyaltyCard card = DBHelper.getLoyaltyCard(activity.getApplicationContext(), database, 1);
- assertEquals(store, card.store);
- assertEquals(note, card.note);
- assertEquals(balance, card.balance);
-
- // The special "Any date" string shouldn't actually be written to the loyalty card
- if (validFrom.equals(activity.getApplicationContext().getString(R.string.anyDate))) {
- assertEquals(null, card.validFrom);
+ private void checkFieldType(final Activity activity, final int id, FieldTypeView fieldTypeView) {
+ final View view = activity.findViewById(id);
+ if (fieldTypeView == FieldTypeView.TextView) {
+ assertTrue(view instanceof TextView);
} else {
- assertEquals(DateFormat.getDateInstance().parse(validFrom), card.validFrom);
+ assertTrue(view instanceof TextInputLayout || view instanceof ImageView);
}
-
- // The special "Never" string shouldn't actually be written to the loyalty card
- if (expiry.equals(activity.getApplicationContext().getString(R.string.never))) {
- assertEquals(null, card.expiry);
- } else {
- assertEquals(DateFormat.getDateInstance().parse(expiry), card.expiry);
- }
-
- // The special "Points" string shouldn't actually be written to the loyalty card
- if (balanceType.equals(activity.getApplicationContext().getString(R.string.points))) {
- assertEquals(null, card.balanceType);
- } else {
- assertEquals(Currency.getInstance(balanceType), card.balanceType);
- }
- assertEquals(cardId, card.cardId);
-
- // The special "Same as barcode ID" string shouldn't actually be written to the loyalty card
- if (barcodeId.equals(activity.getApplicationContext().getString(R.string.sameAsCardId))) {
- assertEquals(null, card.barcodeId);
- } else {
- assertEquals(barcodeId, card.barcodeId);
- }
-
- // The special "No barcode" string shouldn't actually be written to the loyalty card
- if (barcodeType.equals(activity.getApplicationContext().getString(R.string.noBarcode))) {
- assertEquals(null, card.barcodeType);
- } else {
- assertEquals(CatimaBarcode.fromName(barcodeType).format(), card.barcodeType.format());
- }
-
- assertEquals(Charset.forName(barcodeEncoding), card.barcodeEncoding);
-
- assertNotNull(card.headerColor);
-
- database.close();
}
/**
@@ -357,7 +411,7 @@ public class LoyaltyCardViewActivityTest {
@Test
@Config(qualifiers="de")
public void noCrashOnRegionlessLocale() {
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class).create());
LoyaltyCardEditActivity activity = (LoyaltyCardEditActivity) activityController.get();
final Context context = activity.getApplicationContext();
@@ -375,107 +429,110 @@ public class LoyaltyCardViewActivityTest {
@Test
public void noDataLossOnResumeOrRotate() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
+ try {
+ registerMediaStoreIntentHandler();
- registerMediaStoreIntentHandler();
+ Integer cardId;
- Integer cardId;
+ for (boolean newCard : new boolean[]{false, true}) {
+ System.out.println();
+ System.out.println("=====");
+ System.out.println("New card? " + newCard);
+ System.out.println("=====");
+ System.out.println();
- for (boolean newCard : new boolean[]{false, true}) {
- System.out.println();
- System.out.println("=====");
- System.out.println("New card? " + newCard);
- System.out.println("=====");
- System.out.println();
+ if (!newCard) {
+ cardId = (int) DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.UTF_8, Color.BLACK, 0, null, 0);
+ } else {
+ cardId = null;
+ }
- if (!newCard) {
- cardId = (int) DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.UTF_8, Color.BLACK, 0, null, 0);
- } else {
- cardId = null;
+ ActivityController activityController = createActivityWithLoyaltyCard(true, cardId);
+ LoyaltyCardEditActivity activity = (LoyaltyCardEditActivity) activityController.get();
+
+ activityController.start();
+ activityController.visible();
+ activityController.resume();
+
+ shadowOf(getMainLooper()).idle();
+
+ // Check default settings
+ checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, newCard ? "" : "store", newCard ? "" : "note", context.getString(R.string.anyDate), context.getString(R.string.never), "0", context.getString(R.string.points), newCard ? "" : EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), newCard ? context.getString(R.string.noBarcode) : EAN_BARCODE_TYPE.prettyName(), newCard ? "ISO-8859-1" : "UTF-8", null, null);
+
+ // Change everything
+ final EditText storeField = activity.findViewById(R.id.storeNameEdit);
+ final EditText noteField = activity.findViewById(R.id.noteEdit);
+ final EditText validFromField = activity.findViewById(R.id.validFromField);
+ final EditText expiryField = activity.findViewById(R.id.expiryField);
+ final EditText balanceField = activity.findViewById(R.id.balanceField);
+ final EditText balanceTypeField = activity.findViewById(R.id.balanceCurrencyField);
+ final EditText cardIdField = activity.findViewById(R.id.cardIdView);
+ final EditText barcodeField = activity.findViewById(R.id.barcodeIdField);
+ final EditText barcodeTypeField = activity.findViewById(R.id.barcodeTypeField);
+ final EditText barcodeEncodingField = activity.findViewById(R.id.barcodeEncodingField);
+ final ImageView frontImageView = activity.findViewById(R.id.frontImage);
+ final ImageView backImageView = activity.findViewById(R.id.backImage);
+
+ Currency currency = Currency.getInstance("EUR");
+ Date validFromDate = Date.from(Instant.now().minus(20, ChronoUnit.DAYS));
+ Date expiryDate = new Date();
+ Bitmap frontBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.circle);
+ Bitmap backBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_done);
+
+ storeField.setText("correct store");
+ noteField.setText("correct note");
+ LoyaltyCardEditActivity.formatDateField(context, validFromField, validFromDate);
+ activity.setLoyaltyCardValidFrom(validFromDate);
+ LoyaltyCardEditActivity.formatDateField(context, expiryField, expiryDate);
+ activity.setLoyaltyCardExpiry(expiryDate);
+ balanceField.setText("100");
+ balanceTypeField.setText(currency.getSymbol());
+ cardIdField.setText("12345678");
+ barcodeField.setText("87654321");
+ barcodeTypeField.setText(CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName());
+ barcodeEncodingField.setText(StandardCharsets.ISO_8859_1.name());
+ activity.setCardImage(ImageLocationType.front, frontImageView, frontBitmap, true);
+ activity.setCardImage(ImageLocationType.back, backImageView, backBitmap, true);
+
+ shadowOf(getMainLooper()).idle();
+
+ // Check if changed
+ checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(validFromDate), DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName(), StandardCharsets.ISO_8859_1.name(), frontBitmap, backBitmap);
+
+ // Resume
+ activityController.pause();
+ activityController.resume();
+
+ shadowOf(getMainLooper()).idle();
+
+ // Check if no changes lost
+ checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(validFromDate), DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName(), StandardCharsets.ISO_8859_1.name(), frontBitmap, backBitmap);
+
+ // Rotate to landscape
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ activity.recreate();
+ shadowOf(getMainLooper()).idle();
+
+ // Check if no changes lost
+ checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(validFromDate), DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName(), StandardCharsets.ISO_8859_1.name(), frontBitmap, backBitmap);
+
+ // Rotate to portrait
+ shadowOf(getMainLooper()).idle();
+ activity.recreate();
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+
+ // Check if no changes lost
+ checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(validFromDate), DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName(), StandardCharsets.ISO_8859_1.name(), frontBitmap, backBitmap);
}
-
- ActivityController activityController = createActivityWithLoyaltyCard(true, cardId);
- LoyaltyCardEditActivity activity = (LoyaltyCardEditActivity) activityController.get();
-
- activityController.start();
- activityController.visible();
- activityController.resume();
-
- shadowOf(getMainLooper()).idle();
-
- // Check default settings
- checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, newCard ? "" : "store", newCard ? "" : "note", context.getString(R.string.anyDate), context.getString(R.string.never), "0", context.getString(R.string.points), newCard ? "" : EAN_BARCODE_DATA, context.getString(R.string.sameAsCardId), newCard ? context.getString(R.string.noBarcode) : EAN_BARCODE_TYPE.prettyName(), newCard ? "ISO-8859-1" : "UTF-8", null, null);
-
- // Change everything
- final EditText storeField = activity.findViewById(R.id.storeNameEdit);
- final EditText noteField = activity.findViewById(R.id.noteEdit);
- final EditText validFromField = activity.findViewById(R.id.validFromField);
- final EditText expiryField = activity.findViewById(R.id.expiryField);
- final EditText balanceField = activity.findViewById(R.id.balanceField);
- final EditText balanceTypeField = activity.findViewById(R.id.balanceCurrencyField);
- final EditText cardIdField = activity.findViewById(R.id.cardIdView);
- final EditText barcodeField = activity.findViewById(R.id.barcodeIdField);
- final EditText barcodeTypeField = activity.findViewById(R.id.barcodeTypeField);
- final EditText barcodeEncodingField = activity.findViewById(R.id.barcodeEncodingField);
- final ImageView frontImageView = activity.findViewById(R.id.frontImage);
- final ImageView backImageView = activity.findViewById(R.id.backImage);
-
- Currency currency = Currency.getInstance("EUR");
- Date validFromDate = Date.from(Instant.now().minus(20, ChronoUnit.DAYS));
- Date expiryDate = new Date();
- Bitmap frontBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.circle);
- Bitmap backBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_done);
-
- storeField.setText("correct store");
- noteField.setText("correct note");
- LoyaltyCardEditActivity.formatDateField(context, validFromField, validFromDate);
- activity.setLoyaltyCardValidFrom(validFromDate);
- LoyaltyCardEditActivity.formatDateField(context, expiryField, expiryDate);
- activity.setLoyaltyCardExpiry(expiryDate);
- balanceField.setText("100");
- balanceTypeField.setText(currency.getSymbol());
- cardIdField.setText("12345678");
- barcodeField.setText("87654321");
- barcodeTypeField.setText(CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName());
- barcodeEncodingField.setText(StandardCharsets.ISO_8859_1.name());
- activity.setCardImage(ImageLocationType.front, frontImageView, frontBitmap, true);
- activity.setCardImage(ImageLocationType.back, backImageView, backBitmap, true);
-
- shadowOf(getMainLooper()).idle();
-
- // Check if changed
- checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(validFromDate), DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName(), StandardCharsets.ISO_8859_1.name(), frontBitmap, backBitmap);
-
- // Resume
- activityController.pause();
- activityController.resume();
-
- shadowOf(getMainLooper()).idle();
-
- // Check if no changes lost
- checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(validFromDate), DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName(), StandardCharsets.ISO_8859_1.name(), frontBitmap, backBitmap);
-
- // Rotate to landscape
- activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- activity.recreate();
- shadowOf(getMainLooper()).idle();
-
- // Check if no changes lost
- checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(validFromDate), DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName(), StandardCharsets.ISO_8859_1.name(), frontBitmap, backBitmap);
-
- // Rotate to portrait
- shadowOf(getMainLooper()).idle();
- activity.recreate();
- activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-
- // Check if no changes lost
- checkAllFields(activity, newCard ? ViewMode.ADD_CARD : ViewMode.UPDATE_CARD, "correct store", "correct note", DateFormat.getDateInstance(DateFormat.LONG).format(validFromDate), DateFormat.getDateInstance(DateFormat.LONG).format(expiryDate), "100.00", currency.getSymbol(), "12345678", "87654321", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE).prettyName(), StandardCharsets.ISO_8859_1.name(), frontBitmap, backBitmap);
+ } finally {
+ database.close();
}
}
@Test
public void startWithoutParametersCheckFieldsAvailable() {
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class).create());
activityController.start();
activityController.visible();
activityController.resume();
@@ -489,9 +546,9 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithoutParametersCannotCreateLoyaltyCard() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class).create());
activityController.start();
activityController.visible();
activityController.resume();
@@ -519,7 +576,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithoutParametersBack() {
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class).create());
activityController.start();
activityController.visible();
activityController.resume();
@@ -535,7 +592,7 @@ public class LoyaltyCardViewActivityTest {
public void startWithoutParametersCaptureBarcodeCreateLoyaltyCard() throws IOException, ParseException {
registerMediaStoreIntentHandler();
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class).create());
activityController.start();
activityController.visible();
activityController.resume();
@@ -559,7 +616,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithoutParametersCaptureBarcodeFailure() throws IOException {
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class).create());
activityController.start();
activityController.visible();
activityController.resume();
@@ -580,7 +637,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithoutParametersCaptureBarcodeCancel() throws IOException {
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class).create());
activityController.start();
activityController.visible();
activityController.resume();
@@ -631,13 +688,13 @@ public class LoyaltyCardViewActivityTest {
intent.putExtras(bundle);
- return Robolectric.buildActivity(clazz, intent).create();
+ return trackActivityController(Robolectric.buildActivity(clazz, intent).create());
}
@Test
public void startWithLoyaltyCardEditModeCheckDisplay() throws IOException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -656,7 +713,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardViewModeCheckDisplay() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.UTF_8, Color.BLACK, 0, null, 0);
@@ -675,7 +732,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardWithBarcodeUpdateBarcode() throws IOException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.UTF_8, Color.BLACK, 0, null, 0);
@@ -700,7 +757,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardWithReceiptUpdateReceiptCancel() throws IOException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -739,7 +796,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardNoExpirySetExpiry() throws IOException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -772,7 +829,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardExpirySetNoExpiry() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, new Date(), new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -797,7 +854,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardNoBalanceSetBalance() throws IOException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -848,7 +905,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardBalanceSetNoBalance() throws IOException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("10.00"), Currency.getInstance("USD"), EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -889,7 +946,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardSameAsCardIDUpdateBarcodeID() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -921,7 +978,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardSameAsCardIDUpdateCardID() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, null, EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -955,7 +1012,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDUpdate() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, "123456", EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -992,7 +1049,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithLoyaltyCardDifferentFromCardIDUpdateCardIDDoNotUpdate() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, EAN_BARCODE_DATA, "123456", EAN_BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -1029,7 +1086,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void checkMenu() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -1074,7 +1131,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithoutParametersViewBack() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -1095,7 +1152,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startWithoutColors() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.ISO_8859_1, null, 0, null, 0);
@@ -1116,7 +1173,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startLoyaltyCardWithoutColorsSave() throws IOException, ParseException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.ISO_8859_1, null, 0, null, 0);
@@ -1136,7 +1193,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void startLoyaltyCardWithExplicitNoBarcodeSave() throws IOException, ParseException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, null, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -1156,7 +1213,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void removeBarcodeFromLoyaltyCard() throws IOException, ParseException {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -1187,7 +1244,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void checkPushStarIcon() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -1224,7 +1281,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void checkBarcodeFullscreenWorkflow() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -1320,7 +1377,7 @@ public class LoyaltyCardViewActivityTest {
@Test
public void checkNoBarcodeFullscreenWorkflow() {
final Context context = ApplicationProvider.getApplicationContext();
- SQLiteDatabase database = TestHelpers.getEmptyDb(context).getWritableDatabase();
+ SQLiteDatabase database = getWritableEmptyDatabase(context);
long cardId = DBHelper.insertLoyaltyCard(database, "store", "note", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, null, StandardCharsets.ISO_8859_1, Color.BLACK, 0, null, 0);
@@ -1366,7 +1423,7 @@ public class LoyaltyCardViewActivityTest {
Intent intent = new Intent();
intent.setData(importUri);
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class, intent).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class, intent).create());
activityController.start();
activityController.visible();
@@ -1388,7 +1445,7 @@ public class LoyaltyCardViewActivityTest {
Intent intent = new Intent();
intent.setData(importUri);
- ActivityController activityController = Robolectric.buildActivity(LoyaltyCardEditActivity.class, intent).create();
+ ActivityController activityController = trackActivityController(Robolectric.buildActivity(LoyaltyCardEditActivity.class, intent).create());
activityController.start();
activityController.visible();
diff --git a/app/src/test/java/protect/card_locker/TestHelpers.java b/app/src/test/java/protect/card_locker/TestHelpers.java
index 084b04752..1963ead2d 100644
--- a/app/src/test/java/protect/card_locker/TestHelpers.java
+++ b/app/src/test/java/protect/card_locker/TestHelpers.java
@@ -22,19 +22,20 @@ public class TestHelpers {
SQLiteDatabase database = db.getWritableDatabase();
// Make sure no files remain
- Cursor cursor = DBHelper.getLoyaltyCardCursor(database);
- cursor.moveToFirst();
- while (!cursor.isAfterLast()) {
- int cardID = cursor.getColumnIndex(DBHelper.LoyaltyCardDbIds.ID);
+ try (Cursor cursor = DBHelper.getLoyaltyCardCursor(database)) {
+ cursor.moveToFirst();
+ while (!cursor.isAfterLast()) {
+ int cardID = cursor.getColumnIndex(DBHelper.LoyaltyCardDbIds.ID);
- for (ImageLocationType imageLocationType : ImageLocationType.values()) {
- try {
- Utils.saveCardImage(context.getApplicationContext(), null, cardID, imageLocationType);
- } catch (FileNotFoundException ignored) {
+ for (ImageLocationType imageLocationType : ImageLocationType.values()) {
+ try {
+ Utils.saveCardImage(context.getApplicationContext(), null, cardID, imageLocationType);
+ } catch (FileNotFoundException ignored) {
+ }
}
- }
- cursor.moveToNext();
+ cursor.moveToNext();
+ }
}
// Make sure DB is empty