mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2026-02-05 12:43:00 -05:00
Add barcode encoding support
- Add new barcodeencoding field to database - Read barcode encoding from pkpass file - Add barcodeencoding to import/export - Add barcodeencoding to share URI - On default, use zxing's GuessEncoding function in StringUtils (this should not use UTF-8 unless needed) - Allow manually forcing ISO-8859-1 or UTF-8
This commit is contained in:
@@ -4,17 +4,24 @@ import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.common.StringUtils;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
|
||||
import protect.card_locker.async.CompatCallable;
|
||||
|
||||
@@ -39,6 +46,7 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
|
||||
private final WeakReference<TextView> textViewReference;
|
||||
private String cardId;
|
||||
private final CatimaBarcode format;
|
||||
private final Charset encoding;
|
||||
private final int imageHeight;
|
||||
private final int imageWidth;
|
||||
private final int imagePadding;
|
||||
@@ -48,7 +56,7 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
|
||||
|
||||
BarcodeImageWriterTask(
|
||||
Context context, ImageView imageView, String cardIdString,
|
||||
CatimaBarcode barcodeFormat, TextView textView,
|
||||
CatimaBarcode barcodeFormat, @Nullable Charset barcodeEncoding, TextView textView,
|
||||
boolean showFallback, BarcodeImageWriterResultCallback callback, boolean roundCornerPadding, boolean isFullscreen
|
||||
) {
|
||||
mContext = context;
|
||||
@@ -62,6 +70,7 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
|
||||
|
||||
cardId = cardIdString;
|
||||
format = barcodeFormat;
|
||||
encoding = barcodeEncoding;
|
||||
|
||||
int imageViewHeight = imageView.getHeight();
|
||||
int imageViewWidth = imageView.getWidth();
|
||||
@@ -172,10 +181,22 @@ public class BarcodeImageWriterTask implements CompatCallable<Bitmap> {
|
||||
}
|
||||
|
||||
MultiFormatWriter writer = new MultiFormatWriter();
|
||||
|
||||
Map<EncodeHintType, Object> encodeHints = new ArrayMap<>();
|
||||
// Use charset if defined or guess otherwise
|
||||
if (encoding != null) {
|
||||
Log.d(TAG, "Encoding explicitly set, " + encoding.name());
|
||||
encodeHints.put(EncodeHintType.CHARACTER_SET, encoding);
|
||||
} else {
|
||||
String guessedEncoding = StringUtils.guessEncoding(cardId.getBytes(), new ArrayMap<>());
|
||||
Log.d(TAG, "Guessed encoding: " + guessedEncoding);
|
||||
encodeHints.put(EncodeHintType.CHARACTER_SET, Charset.forName(guessedEncoding));
|
||||
}
|
||||
|
||||
BitMatrix bitMatrix;
|
||||
try {
|
||||
try {
|
||||
bitMatrix = writer.encode(cardId, format.format(), imageWidth, imageHeight, null);
|
||||
bitMatrix = writer.encode(cardId, format.format(), imageWidth, imageHeight, encodeHints);
|
||||
} catch (Exception e) {
|
||||
// Cast a wider net here and catch any exception, as there are some
|
||||
// cases where an encoder may fail if the data is invalid for the
|
||||
|
||||
@@ -92,13 +92,13 @@ public class BarcodeSelectorAdapter extends ArrayAdapter<CatimaBarcodeWithValue>
|
||||
|
||||
Log.d(TAG, "Generating barcode for type " + formatType);
|
||||
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getContext(), image, cardId, format, text, true, null, true, false);
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getContext(), image, cardId, format, null, text, true, null, true, false);
|
||||
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.d(TAG, "Generating barcode for type " + formatType);
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getContext(), image, cardId, format, text, true, null, true, false);
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getContext(), image, cardId, format, null, text, true, null, true, false);
|
||||
mTasks.executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,11 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Currency;
|
||||
@@ -23,7 +26,7 @@ import java.util.Set;
|
||||
public class DBHelper extends SQLiteOpenHelper {
|
||||
public static final String DATABASE_NAME = "Catima.db";
|
||||
public static final int ORIGINAL_DATABASE_VERSION = 1;
|
||||
public static final int DATABASE_VERSION = 17;
|
||||
public static final int DATABASE_VERSION = 18;
|
||||
|
||||
// NB: changing these values requires a migration
|
||||
public static final int DEFAULT_ZOOM_LEVEL = 100;
|
||||
@@ -49,6 +52,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
public static final String CARD_ID = "cardid";
|
||||
public static final String BARCODE_ID = "barcodeid";
|
||||
public static final String BARCODE_TYPE = "barcodetype";
|
||||
public static final String BARCODE_ENCODING = "barcodeencoding";
|
||||
public static final String STAR_STATUS = "starstatus";
|
||||
public static final String LAST_USED = "lastused";
|
||||
public static final String ZOOM_LEVEL = "zoomlevel";
|
||||
@@ -112,6 +116,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
LoyaltyCardDbIds.CARD_ID + " TEXT not null," +
|
||||
LoyaltyCardDbIds.BARCODE_ID + " TEXT," +
|
||||
LoyaltyCardDbIds.BARCODE_TYPE + " TEXT," +
|
||||
LoyaltyCardDbIds.BARCODE_ENCODING + " TEXT," +
|
||||
LoyaltyCardDbIds.STAR_STATUS + " INTEGER DEFAULT '0'," +
|
||||
LoyaltyCardDbIds.LAST_USED + " INTEGER DEFAULT '0', " +
|
||||
LoyaltyCardDbIds.ZOOM_LEVEL + " INTEGER DEFAULT '" + DEFAULT_ZOOM_LEVEL + "', " +
|
||||
@@ -335,6 +340,11 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.ZOOM_LEVEL_WIDTH + " INTEGER DEFAULT '100' ");
|
||||
}
|
||||
|
||||
if (oldVersion < 18 && newVersion >= 18) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.BARCODE_ENCODING + " TEXT");
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> imageFiles(Context context, final SQLiteDatabase database) {
|
||||
@@ -396,7 +406,8 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
public static long insertLoyaltyCard(
|
||||
final SQLiteDatabase database, final String store, final String note, final Date validFrom,
|
||||
final Date expiry, final BigDecimal balance, final Currency balanceType, final String cardId,
|
||||
final String barcodeId, final CatimaBarcode barcodeType, final Integer headerColor,
|
||||
final String barcodeId, final CatimaBarcode barcodeType, final @Nullable Charset barcodeEncoding,
|
||||
final Integer headerColor,
|
||||
final int starStatus, final Long lastUsed, final int archiveStatus) {
|
||||
database.beginTransaction();
|
||||
|
||||
@@ -411,6 +422,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
contentValues.put(LoyaltyCardDbIds.CARD_ID, cardId);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_ID, barcodeId);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.name() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_ENCODING, barcodeEncoding != null ? barcodeEncoding.name() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
|
||||
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
|
||||
@@ -430,7 +442,8 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
final SQLiteDatabase database, final int id, final String store, final String note,
|
||||
final Date validFrom, final Date expiry, final BigDecimal balance,
|
||||
final Currency balanceType, final String cardId, final String barcodeId,
|
||||
final CatimaBarcode barcodeType, final Integer headerColor, final int starStatus,
|
||||
final CatimaBarcode barcodeType, final @Nullable Charset barcodeEncoding,
|
||||
final Integer headerColor, final int starStatus,
|
||||
final Long lastUsed, final int archiveStatus) {
|
||||
database.beginTransaction();
|
||||
|
||||
@@ -446,6 +459,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
contentValues.put(LoyaltyCardDbIds.CARD_ID, cardId);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_ID, barcodeId);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.name() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_ENCODING, barcodeEncoding != null ? barcodeEncoding.name() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
|
||||
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
|
||||
@@ -465,7 +479,8 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
SQLiteDatabase database, final int id, final String store, final String note,
|
||||
final Date validFrom, final Date expiry, final BigDecimal balance,
|
||||
final Currency balanceType, final String cardId, final String barcodeId,
|
||||
final CatimaBarcode barcodeType, final Integer headerColor, final int starStatus,
|
||||
final CatimaBarcode barcodeType, final @Nullable Charset barcodeEncoding,
|
||||
final Integer headerColor, final int starStatus,
|
||||
final Long lastUsed, final int archiveStatus) {
|
||||
database.beginTransaction();
|
||||
|
||||
@@ -480,6 +495,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
contentValues.put(LoyaltyCardDbIds.CARD_ID, cardId);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_ID, barcodeId);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.name() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_ENCODING, barcodeEncoding != null ? barcodeEncoding.name() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
|
||||
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
|
||||
|
||||
@@ -4,11 +4,14 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Currency;
|
||||
import java.util.Date;
|
||||
@@ -25,6 +28,7 @@ public class ImportURIHelper {
|
||||
private static final String CARD_ID = DBHelper.LoyaltyCardDbIds.CARD_ID;
|
||||
private static final String BARCODE_ID = DBHelper.LoyaltyCardDbIds.BARCODE_ID;
|
||||
private static final String BARCODE_TYPE = DBHelper.LoyaltyCardDbIds.BARCODE_TYPE;
|
||||
private static final String BARCODE_ENCODING = DBHelper.LoyaltyCardDbIds.BARCODE_ENCODING;
|
||||
private static final String HEADER_COLOR = DBHelper.LoyaltyCardDbIds.HEADER_COLOR;
|
||||
|
||||
private final Context context;
|
||||
@@ -66,6 +70,7 @@ public class ImportURIHelper {
|
||||
try {
|
||||
// These values are allowed to be null
|
||||
CatimaBarcode barcodeType = null;
|
||||
Charset barcodeEncoding = null;
|
||||
Date validFrom = null;
|
||||
Date expiry = null;
|
||||
BigDecimal balance = new BigDecimal("0");
|
||||
@@ -103,6 +108,11 @@ public class ImportURIHelper {
|
||||
barcodeType = CatimaBarcode.fromName(unparsedBarcodeType);
|
||||
}
|
||||
|
||||
String unparsedBarcodeEncoding = kv.get(BARCODE_ENCODING);
|
||||
if (unparsedBarcodeEncoding != null && !unparsedBarcodeEncoding.equals("")) {
|
||||
barcodeEncoding = Charset.forName(unparsedBarcodeEncoding);
|
||||
}
|
||||
|
||||
String unparsedBalance = kv.get(BALANCE);
|
||||
if (unparsedBalance != null && !unparsedBalance.equals("")) {
|
||||
balance = new BigDecimal(unparsedBalance);
|
||||
@@ -136,6 +146,7 @@ public class ImportURIHelper {
|
||||
cardId,
|
||||
barcodeId,
|
||||
barcodeType,
|
||||
barcodeEncoding,
|
||||
headerColor,
|
||||
0,
|
||||
Utils.getUnixTime(),
|
||||
@@ -195,6 +206,9 @@ public class ImportURIHelper {
|
||||
if (loyaltyCard.barcodeType != null) {
|
||||
fragment = appendFragment(fragment, BARCODE_TYPE, loyaltyCard.barcodeType.name());
|
||||
}
|
||||
if (loyaltyCard.barcodeEncoding != null) {
|
||||
fragment = appendFragment(fragment, BARCODE_ENCODING, loyaltyCard.barcodeEncoding.name());
|
||||
}
|
||||
if (loyaltyCard.headerColor != null) {
|
||||
fragment = appendFragment(fragment, HEADER_COLOR, loyaltyCard.headerColor.toString());
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Currency;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -31,6 +32,8 @@ public class LoyaltyCard {
|
||||
@Nullable
|
||||
public CatimaBarcode barcodeType;
|
||||
@Nullable
|
||||
public Charset barcodeEncoding;
|
||||
@Nullable
|
||||
public Integer headerColor;
|
||||
public int starStatus;
|
||||
public long lastUsed;
|
||||
@@ -62,6 +65,7 @@ public class LoyaltyCard {
|
||||
public static final String BUNDLE_LOYALTY_CARD_CARD_ID = "loyaltyCardCardId";
|
||||
public static final String BUNDLE_LOYALTY_CARD_BARCODE_ID = "loyaltyCardBarcodeId";
|
||||
public static final String BUNDLE_LOYALTY_CARD_BARCODE_TYPE = "loyaltyCardBarcodeType";
|
||||
public static final String BUNDLE_LOYALTY_CARD_BARCODE_ENCODING = "loyaltyCardBarcodeEncoding";
|
||||
public static final String BUNDLE_LOYALTY_CARD_HEADER_COLOR = "loyaltyCardHeaderColor";
|
||||
public static final String BUNDLE_LOYALTY_CARD_STAR_STATUS = "loyaltyCardStarStatus";
|
||||
public static final String BUNDLE_LOYALTY_CARD_LAST_USED = "loyaltyCardLastUsed";
|
||||
@@ -90,6 +94,7 @@ public class LoyaltyCard {
|
||||
setCardId("");
|
||||
setBarcodeId(null);
|
||||
setBarcodeType(null);
|
||||
setBarcodeEncoding(null);
|
||||
setHeaderColor(null);
|
||||
setStarStatus(0);
|
||||
setLastUsed(Utils.getUnixTime());
|
||||
@@ -124,7 +129,7 @@ public class LoyaltyCard {
|
||||
public LoyaltyCard(final int id, final String store, final String note, @Nullable final Date validFrom,
|
||||
@Nullable final Date expiry, final BigDecimal balance, @Nullable final Currency balanceType,
|
||||
final String cardId, @Nullable final String barcodeId, @Nullable final CatimaBarcode barcodeType,
|
||||
@Nullable final Integer headerColor, final int starStatus,
|
||||
@Nullable final Charset barcodeEncoding, @Nullable final Integer headerColor, final int starStatus,
|
||||
final long lastUsed, final int zoomLevel, final int zoomLevelWidth, final int archiveStatus,
|
||||
@Nullable Bitmap imageThumbnail, @Nullable String imageThumbnailPath,
|
||||
@Nullable Bitmap imageFront, @Nullable String imageFrontPath,
|
||||
@@ -139,6 +144,7 @@ public class LoyaltyCard {
|
||||
setCardId(cardId);
|
||||
setBarcodeId(barcodeId);
|
||||
setBarcodeType(barcodeType);
|
||||
setBarcodeEncoding(barcodeEncoding);
|
||||
setHeaderColor(headerColor);
|
||||
setStarStatus(starStatus);
|
||||
setLastUsed(lastUsed);
|
||||
@@ -244,6 +250,10 @@ public class LoyaltyCard {
|
||||
this.barcodeType = barcodeType;
|
||||
}
|
||||
|
||||
public void setBarcodeEncoding(@Nullable Charset barcodeEncoding) {
|
||||
this.barcodeEncoding = barcodeEncoding;
|
||||
}
|
||||
|
||||
public void setHeaderColor(@Nullable Integer headerColor) {
|
||||
this.headerColor = headerColor;
|
||||
}
|
||||
@@ -379,6 +389,11 @@ public class LoyaltyCard {
|
||||
} else if (requireFull) {
|
||||
throw new IllegalArgumentException("Missing key " + BUNDLE_LOYALTY_CARD_BARCODE_TYPE);
|
||||
}
|
||||
if (bundle.containsKey(BUNDLE_LOYALTY_CARD_BARCODE_ENCODING)) {
|
||||
setBarcodeEncoding(Charset.forName(bundle.getString(BUNDLE_LOYALTY_CARD_BARCODE_ENCODING)));
|
||||
} else if (requireFull) {
|
||||
throw new IllegalArgumentException("Missing key " + BUNDLE_LOYALTY_CARD_BARCODE_ENCODING);
|
||||
}
|
||||
if (bundle.containsKey(BUNDLE_LOYALTY_CARD_HEADER_COLOR)) {
|
||||
int tmpHeaderColor = bundle.getInt(BUNDLE_LOYALTY_CARD_HEADER_COLOR);
|
||||
setHeaderColor(tmpHeaderColor != -1 ? tmpHeaderColor : null);
|
||||
@@ -462,6 +477,9 @@ public class LoyaltyCard {
|
||||
if (!exportIsLimited || exportLimit.contains(BUNDLE_LOYALTY_CARD_BARCODE_TYPE)) {
|
||||
bundle.putString(BUNDLE_LOYALTY_CARD_BARCODE_TYPE, barcodeType != null ? barcodeType.name() : null);
|
||||
}
|
||||
if (!exportIsLimited || exportLimit.contains(BUNDLE_LOYALTY_CARD_BARCODE_ENCODING)) {
|
||||
bundle.putString(BUNDLE_LOYALTY_CARD_BARCODE_ENCODING, barcodeEncoding != null ? barcodeEncoding.name() : null);
|
||||
}
|
||||
if (!exportIsLimited || exportLimit.contains(BUNDLE_LOYALTY_CARD_HEADER_COLOR)) {
|
||||
bundle.putInt(BUNDLE_LOYALTY_CARD_HEADER_COLOR, headerColor != null ? headerColor : -1);
|
||||
}
|
||||
@@ -539,6 +557,9 @@ public class LoyaltyCard {
|
||||
// barcodeType
|
||||
int barcodeTypeColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE);
|
||||
CatimaBarcode barcodeType = !cursor.isNull(barcodeTypeColumn) ? CatimaBarcode.fromName(cursor.getString(barcodeTypeColumn)) : null;
|
||||
// barcodeEncoding
|
||||
int barcodeEncodingColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ENCODING);
|
||||
Charset barcodeEncoding = !cursor.isNull(barcodeEncodingColumn) ? Charset.forName(cursor.getString(barcodeEncodingColumn)) : null;
|
||||
// headerColor
|
||||
int headerColorColumn = cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR);
|
||||
Integer headerColor = !cursor.isNull(headerColorColumn) ? cursor.getInt(headerColorColumn) : null;
|
||||
@@ -564,6 +585,7 @@ public class LoyaltyCard {
|
||||
cardId,
|
||||
barcodeId,
|
||||
barcodeType,
|
||||
barcodeEncoding,
|
||||
headerColor,
|
||||
starStatus,
|
||||
lastUsed,
|
||||
@@ -593,6 +615,7 @@ public class LoyaltyCard {
|
||||
Utils.equals(a.barcodeId, b.barcodeId) && // nullable String
|
||||
Utils.equals(a.barcodeType == null ? null : a.barcodeType.format(),
|
||||
b.barcodeType == null ? null : b.barcodeType.format()) && // nullable CatimaBarcode with no overridden .equals(), so we need to check .format()
|
||||
Utils.equals(a.barcodeEncoding, b.barcodeEncoding) && // nullable String
|
||||
Utils.equals(a.headerColor, b.headerColor) && // nullable Integer
|
||||
a.starStatus == b.starStatus && // non-nullable int
|
||||
a.archiveStatus == b.archiveStatus && // non-nullable int
|
||||
@@ -619,7 +642,7 @@ public class LoyaltyCard {
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"LoyaltyCard{%n id=%s,%n store=%s,%n note=%s,%n validFrom=%s,%n expiry=%s,%n"
|
||||
+ " balance=%s,%n balanceType=%s,%n cardId=%s,%n barcodeId=%s,%n barcodeType=%s,%n"
|
||||
+ " balance=%s,%n balanceType=%s,%n cardId=%s,%n barcodeId=%s,%n barcodeType=%s,%n barcodeEncoding=%s,%n"
|
||||
+ " headerColor=%s,%n starStatus=%s,%n lastUsed=%s,%n zoomLevel=%s,%n zoomLevelWidth=%s,%n archiveStatus=%s%n"
|
||||
+ " imageThumbnail=%s,%n imageThumbnailPath=%s,%n imageFront=%s,%n imageFrontPath=%s,%n imageBack=%s,%n imageBackPath=%s,%n}",
|
||||
this.id,
|
||||
@@ -632,6 +655,7 @@ public class LoyaltyCard {
|
||||
this.cardId,
|
||||
this.barcodeId,
|
||||
this.barcodeType != null ? this.barcodeType.format() : null,
|
||||
this.barcodeEncoding != null ? this.barcodeEncoding.name() : null,
|
||||
this.headerColor,
|
||||
this.starStatus,
|
||||
this.lastUsed,
|
||||
|
||||
@@ -70,6 +70,8 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
@@ -128,6 +130,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
TextView cardIdFieldView;
|
||||
AutoCompleteTextView barcodeIdField;
|
||||
AutoCompleteTextView barcodeTypeField;
|
||||
AutoCompleteTextView barcodeEncodingField;
|
||||
ImageView barcodeImage;
|
||||
View barcodeImageLayout;
|
||||
View barcodeCaptureLayout;
|
||||
@@ -229,6 +232,14 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
viewModel.setHasChanged(true);
|
||||
}
|
||||
|
||||
protected void setLoyaltyCardBarcodeEncoding(@Nullable Charset barcodeEncoding) {
|
||||
viewModel.getLoyaltyCard().setBarcodeEncoding(barcodeEncoding);
|
||||
|
||||
generateBarcode();
|
||||
|
||||
viewModel.setHasChanged(true);
|
||||
}
|
||||
|
||||
protected void setLoyaltyCardHeaderColor(@Nullable Integer headerColor) {
|
||||
viewModel.getLoyaltyCard().setHeaderColor(headerColor);
|
||||
|
||||
@@ -334,6 +345,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
cardIdFieldView = binding.cardIdView;
|
||||
barcodeIdField = binding.barcodeIdField;
|
||||
barcodeTypeField = binding.barcodeTypeField;
|
||||
barcodeEncodingField = binding.barcodeEncodingField;
|
||||
barcodeImage = binding.barcode;
|
||||
barcodeImage.setClipToOutline(true);
|
||||
barcodeImageLayout = binding.barcodeLayout;
|
||||
@@ -577,6 +589,30 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
}
|
||||
});
|
||||
|
||||
barcodeEncodingField.addTextChangedListener(new SimpleTextWatcher() {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (!s.toString().isEmpty()) {
|
||||
Log.d(TAG, "Setting barcode encoding to " + s.toString());
|
||||
if (s.toString().equals(getString(R.string.automatic))) {
|
||||
setLoyaltyCardBarcodeEncoding(null);
|
||||
} else {
|
||||
setLoyaltyCardBarcodeEncoding(Charset.forName(s.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
ArrayList<String> barcodeEncodingList = new ArrayList<>();
|
||||
barcodeEncodingList.add(getString(R.string.automatic));
|
||||
barcodeEncodingList.add(StandardCharsets.ISO_8859_1.name());
|
||||
barcodeEncodingList.add(StandardCharsets.UTF_8.name());
|
||||
ArrayAdapter<String> barcodeEncodingAdapter = new ArrayAdapter<>(LoyaltyCardEditActivity.this, android.R.layout.select_dialog_item, barcodeEncodingList);
|
||||
barcodeEncodingField.setAdapter(barcodeEncodingAdapter);
|
||||
}
|
||||
});
|
||||
|
||||
binding.tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
@@ -773,6 +809,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
barcodeIdField.setText(barcodeId != null && !barcodeId.isEmpty() ? barcodeId : getString(R.string.sameAsCardId));
|
||||
CatimaBarcode barcodeType = viewModel.getLoyaltyCard().barcodeType;
|
||||
barcodeTypeField.setText(barcodeType != null ? barcodeType.prettyName() : getString(R.string.noBarcode));
|
||||
Charset barcodeEncoding = viewModel.getLoyaltyCard().barcodeEncoding;
|
||||
barcodeEncodingField.setText(barcodeEncoding != null ? barcodeEncoding.name() : getString(R.string.automatic));
|
||||
|
||||
// We set the balance here (with onResuming/onRestoring == true) to prevent formatBalanceCurrencyField() from setting it (via onTextChanged),
|
||||
// which can cause issues when switching locale because it parses the balance and e.g. the decimal separator may have changed.
|
||||
@@ -1479,9 +1517,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
// This makes the DBHelper set it to the current date
|
||||
// So that new and edited card are always on top when sorting by recently used
|
||||
if (viewModel.getUpdateLoyaltyCard()) {
|
||||
DBHelper.updateLoyaltyCard(mDatabase, viewModel.getLoyaltyCardId(), viewModel.getLoyaltyCard().store, viewModel.getLoyaltyCard().note, viewModel.getLoyaltyCard().validFrom, viewModel.getLoyaltyCard().expiry, viewModel.getLoyaltyCard().balance, viewModel.getLoyaltyCard().balanceType, viewModel.getLoyaltyCard().cardId, viewModel.getLoyaltyCard().barcodeId, viewModel.getLoyaltyCard().barcodeType, viewModel.getLoyaltyCard().headerColor, viewModel.getLoyaltyCard().starStatus, null, viewModel.getLoyaltyCard().archiveStatus);
|
||||
DBHelper.updateLoyaltyCard(mDatabase, viewModel.getLoyaltyCardId(), viewModel.getLoyaltyCard().store, viewModel.getLoyaltyCard().note, viewModel.getLoyaltyCard().validFrom, viewModel.getLoyaltyCard().expiry, viewModel.getLoyaltyCard().balance, viewModel.getLoyaltyCard().balanceType, viewModel.getLoyaltyCard().cardId, viewModel.getLoyaltyCard().barcodeId, viewModel.getLoyaltyCard().barcodeType, viewModel.getLoyaltyCard().barcodeEncoding, viewModel.getLoyaltyCard().headerColor, viewModel.getLoyaltyCard().starStatus, null, viewModel.getLoyaltyCard().archiveStatus);
|
||||
} else {
|
||||
viewModel.setLoyaltyCardId((int) DBHelper.insertLoyaltyCard(mDatabase, viewModel.getLoyaltyCard().store, viewModel.getLoyaltyCard().note, viewModel.getLoyaltyCard().validFrom, viewModel.getLoyaltyCard().expiry, viewModel.getLoyaltyCard().balance, viewModel.getLoyaltyCard().balanceType, viewModel.getLoyaltyCard().cardId, viewModel.getLoyaltyCard().barcodeId, viewModel.getLoyaltyCard().barcodeType, viewModel.getLoyaltyCard().headerColor, 0, null, 0));
|
||||
viewModel.setLoyaltyCardId((int) DBHelper.insertLoyaltyCard(mDatabase, viewModel.getLoyaltyCard().store, viewModel.getLoyaltyCard().note, viewModel.getLoyaltyCard().validFrom, viewModel.getLoyaltyCard().expiry, viewModel.getLoyaltyCard().balance, viewModel.getLoyaltyCard().balanceType, viewModel.getLoyaltyCard().cardId, viewModel.getLoyaltyCard().barcodeId, viewModel.getLoyaltyCard().barcodeType, viewModel.getLoyaltyCard().barcodeEncoding, viewModel.getLoyaltyCard().headerColor, 0, null, 0));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1596,6 +1634,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
|
||||
String cardIdString = viewModel.getLoyaltyCard().barcodeId != null ? viewModel.getLoyaltyCard().barcodeId : viewModel.getLoyaltyCard().cardId;
|
||||
CatimaBarcode barcodeFormat = viewModel.getLoyaltyCard().barcodeType;
|
||||
Charset barcodeEncoding = viewModel.getLoyaltyCard().barcodeEncoding;
|
||||
|
||||
if (cardIdString == null || cardIdString.isEmpty() || barcodeFormat == null) {
|
||||
barcodeImageLayout.setVisibility(View.GONE);
|
||||
@@ -1615,13 +1654,13 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
barcodeImage.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
|
||||
Log.d(TAG, "ImageView size now known");
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), barcodeImage, cardIdString, barcodeFormat, null, false, LoyaltyCardEditActivity.this, true, false);
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), barcodeImage, cardIdString, barcodeFormat, barcodeEncoding, null, false, LoyaltyCardEditActivity.this, true, false);
|
||||
viewModel.getTaskHandler().executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.d(TAG, "ImageView size known known, creating barcode");
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), barcodeImage, cardIdString, barcodeFormat, null, false, this, true, false);
|
||||
BarcodeImageWriterTask barcodeWriter = new BarcodeImageWriterTask(getApplicationContext(), barcodeImage, cardIdString, barcodeFormat, barcodeEncoding, null, false, this, true, false);
|
||||
viewModel.getTaskHandler().executeTask(TaskHandler.TYPE.BARCODE, barcodeWriter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
@@ -58,6 +59,7 @@ import com.google.zxing.BarcodeFormat;
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
@@ -87,6 +89,8 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
String cardIdString;
|
||||
String barcodeIdString;
|
||||
CatimaBarcode format;
|
||||
@Nullable
|
||||
Charset barcodeEncoding;
|
||||
|
||||
Bitmap frontImageBitmap;
|
||||
Bitmap backImageBitmap;
|
||||
@@ -686,6 +690,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
format = loyaltyCard.barcodeType;
|
||||
cardIdString = loyaltyCard.cardId;
|
||||
barcodeIdString = loyaltyCard.barcodeId;
|
||||
barcodeEncoding = loyaltyCard.barcodeEncoding;
|
||||
|
||||
binding.mainImageDescription.setText(loyaltyCard.cardId);
|
||||
|
||||
@@ -959,6 +964,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
barcodeRenderTarget,
|
||||
barcodeIdString != null ? barcodeIdString : cardIdString,
|
||||
format,
|
||||
barcodeEncoding,
|
||||
null,
|
||||
false,
|
||||
this,
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.json.JSONObject
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.math.BigDecimal
|
||||
import java.nio.charset.Charset
|
||||
import java.text.DateFormat
|
||||
import java.text.ParseException
|
||||
import java.time.ZonedDateTime
|
||||
@@ -40,6 +41,7 @@ class PkpassParser(context: Context, uri: Uri?) {
|
||||
private var cardId: String = context.getString(R.string.noBarcode)
|
||||
private var barcodeId: String? = null
|
||||
private var barcodeType: CatimaBarcode? = null
|
||||
private var barcodeEncoding: Charset? = null
|
||||
private var headerColor: Int? = null
|
||||
private val starStatus = 0
|
||||
private val lastUsed: Long = 0
|
||||
@@ -134,6 +136,7 @@ class PkpassParser(context: Context, uri: Uri?) {
|
||||
cardId,
|
||||
barcodeId,
|
||||
barcodeType,
|
||||
barcodeEncoding,
|
||||
headerColor,
|
||||
starStatus,
|
||||
lastUsed,
|
||||
@@ -342,13 +345,14 @@ class PkpassParser(context: Context, uri: Uri?) {
|
||||
else -> throw IllegalArgumentException("No valid barcode type")
|
||||
}
|
||||
|
||||
// FIXME: We probably need to do something with the messageEncoding field
|
||||
try {
|
||||
cardId = barcodeInfo.getString("altText")
|
||||
barcodeId = barcodeInfo.getString("message")
|
||||
barcodeEncoding = Charset.forName(barcodeInfo.getString("messageEncoding"))
|
||||
} catch (ignored: JSONException) {
|
||||
cardId = barcodeInfo.getString("message")
|
||||
barcodeId = null
|
||||
barcodeEncoding = Charset.forName(barcodeInfo.getString("messageEncoding"))
|
||||
}
|
||||
|
||||
// Don't set barcodeId if it's the same as cardId
|
||||
|
||||
@@ -52,6 +52,7 @@ public class CardsContentProvider extends ContentProvider {
|
||||
LoyaltyCardDbIds.CARD_ID,
|
||||
LoyaltyCardDbIds.BARCODE_ID,
|
||||
LoyaltyCardDbIds.BARCODE_TYPE,
|
||||
// FIXME: Expose BARCODE_ENCODING but without ever exposing the null value (so apps using this don't have to guess)
|
||||
LoyaltyCardDbIds.STAR_STATUS,
|
||||
LoyaltyCardDbIds.LAST_USED,
|
||||
LoyaltyCardDbIds.ARCHIVE_STATUS,
|
||||
|
||||
@@ -134,6 +134,7 @@ public class CatimaExporter implements Exporter {
|
||||
DBHelper.LoyaltyCardDbIds.CARD_ID,
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_ID,
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE,
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_ENCODING,
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR,
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS,
|
||||
DBHelper.LoyaltyCardDbIds.LAST_USED,
|
||||
@@ -154,6 +155,7 @@ public class CatimaExporter implements Exporter {
|
||||
card.cardId,
|
||||
card.barcodeId,
|
||||
card.barcodeType != null ? card.barcodeType.name() : "",
|
||||
card.barcodeEncoding != null ? card.barcodeEncoding.name() : "",
|
||||
card.headerColor,
|
||||
card.starStatus,
|
||||
card.lastUsed,
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Currency;
|
||||
@@ -127,10 +128,10 @@ public class CatimaImporter implements Importer {
|
||||
LoyaltyCard existing = DBHelper.getLoyaltyCard(context, database, card.id);
|
||||
if (existing == null) {
|
||||
DBHelper.insertLoyaltyCard(database, card.id, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
|
||||
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
|
||||
card.cardId, card.barcodeId, card.barcodeType, card.barcodeEncoding, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
|
||||
} else if (!isDuplicate(context, existing, card, existingImages, imageChecksums)) {
|
||||
long newId = DBHelper.insertLoyaltyCard(database, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
|
||||
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
|
||||
card.cardId, card.barcodeId, card.barcodeType, card.barcodeEncoding, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
|
||||
idMap.put(card.id, (int) newId);
|
||||
}
|
||||
}
|
||||
@@ -458,6 +459,12 @@ public class CatimaImporter implements Importer {
|
||||
barcodeType = CatimaBarcode.fromName(unparsedBarcodeType);
|
||||
}
|
||||
|
||||
Charset barcodeEncoding = null;
|
||||
String unparsedBarcodeEncoding = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BARCODE_ENCODING, record, "");
|
||||
if (!unparsedBarcodeEncoding.isEmpty()) {
|
||||
barcodeEncoding = Charset.forName(unparsedBarcodeEncoding);
|
||||
}
|
||||
|
||||
Integer headerColor = null;
|
||||
try {
|
||||
headerColor = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.HEADER_COLOR, record);
|
||||
@@ -501,6 +508,7 @@ public class CatimaImporter implements Importer {
|
||||
cardId,
|
||||
barcodeId,
|
||||
barcodeType,
|
||||
barcodeEncoding,
|
||||
headerColor,
|
||||
starStatus,
|
||||
lastUsed,
|
||||
|
||||
@@ -160,6 +160,7 @@ public class FidmeImporter implements Importer {
|
||||
cardId,
|
||||
null,
|
||||
barcodeType,
|
||||
null,
|
||||
headerColor,
|
||||
starStatus,
|
||||
Utils.getUnixTime(),
|
||||
@@ -181,7 +182,7 @@ public class FidmeImporter implements Importer {
|
||||
for (LoyaltyCard card : data.cards) {
|
||||
// Do not use card.id which is set to -1
|
||||
DBHelper.insertLoyaltyCard(database, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
|
||||
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
|
||||
card.cardId, card.barcodeId, card.barcodeType, card.barcodeEncoding, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,6 +162,7 @@ public class VoucherVaultImporter implements Importer {
|
||||
cardId,
|
||||
null,
|
||||
barcodeType,
|
||||
null,
|
||||
headerColor,
|
||||
0,
|
||||
Utils.getUnixTime(),
|
||||
@@ -186,7 +187,7 @@ public class VoucherVaultImporter implements Importer {
|
||||
for (LoyaltyCard card : data.cards) {
|
||||
// Do not use card.id which is set to -1
|
||||
DBHelper.insertLoyaltyCard(database, card.store, card.note, card.validFrom, card.expiry, card.balance, card.balanceType,
|
||||
card.cardId, card.barcodeId, card.barcodeType, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
|
||||
card.cardId, card.barcodeId, card.barcodeType, card.barcodeEncoding, card.headerColor, card.starStatus, card.lastUsed, card.archiveStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user