mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2026-04-14 12:27:38 -04:00
Merge pull request #173 from TheLastProject/feature/import-local-image
Added ability to import a barcode from a local image
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
Changes:
|
||||
|
||||
- Support importing [Fidme](https://play.google.com/store/apps/details?id=fr.snapp.fidme) exports
|
||||
- Allow importing a card from a picture stored in the user's Android gallery
|
||||
- Fix multiline note cutoff
|
||||
- Change "Thank you" text on privacy dialog to "Accept" because Huawei is overly pedantic
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@@ -76,6 +77,8 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
View barcodeImageLayout;
|
||||
View barcodeCaptureLayout;
|
||||
|
||||
Button captureButton;
|
||||
Button importImageButton;
|
||||
Button enterButton;
|
||||
|
||||
int loyaltyCardId;
|
||||
@@ -634,6 +637,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ColorSelectListener implements View.OnClickListener
|
||||
{
|
||||
final int defaultColor;
|
||||
@@ -840,7 +844,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent);
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
|
||||
|
||||
barcodeType = barcodeValues.format();
|
||||
cardId = barcodeValues.content();
|
||||
|
||||
@@ -188,7 +188,7 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
|
||||
return;
|
||||
}
|
||||
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent);
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
|
||||
|
||||
if(!barcodeValues.isEmpty()) {
|
||||
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
|
||||
|
||||
@@ -132,7 +132,7 @@ public class ScanActivity extends AppCompatActivity {
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent);
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this);
|
||||
|
||||
if (!barcodeValues.isEmpty()) {
|
||||
Intent manualResult = new Intent();
|
||||
@@ -154,4 +154,10 @@ public class ScanActivity extends AppCompatActivity {
|
||||
}
|
||||
startActivityForResult(i, Utils.SELECT_BARCODE_REQUEST);
|
||||
}
|
||||
|
||||
public void addFromImage(View view) {
|
||||
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
|
||||
photoPickerIntent.setType("image/*");
|
||||
startActivityForResult(photoPickerIntent, Utils.BARCODE_IMPORT_FROM_IMAGE_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,21 +3,31 @@ package protect.card_locker;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Currency;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.LuminanceSource;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.RGBLuminanceSource;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
|
||||
public class Utils {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
@@ -25,6 +35,7 @@ public class Utils {
|
||||
public static final int MAIN_REQUEST = 1;
|
||||
public static final int SELECT_BARCODE_REQUEST = 2;
|
||||
public static final int BARCODE_SCAN = 3;
|
||||
public static final int BARCODE_IMPORT_FROM_IMAGE_FILE = 4;
|
||||
|
||||
static final double LUMINANCE_MIDPOINT = 0.5;
|
||||
|
||||
@@ -48,28 +59,75 @@ public class Utils {
|
||||
return ColorUtils.calculateLuminance(backgroundColor) > LUMINANCE_MIDPOINT;
|
||||
}
|
||||
|
||||
static public BarcodeValues parseSetBarcodeActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
String contents = null;
|
||||
String format = null;
|
||||
static public BarcodeValues parseSetBarcodeActivityResult(int requestCode, int resultCode, Intent intent, Context context) {
|
||||
String contents;
|
||||
String format;
|
||||
|
||||
if (resultCode == Activity.RESULT_OK)
|
||||
{
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
return new BarcodeValues(null, null);
|
||||
}
|
||||
|
||||
if (requestCode == Utils.BARCODE_IMPORT_FROM_IMAGE_FILE) {
|
||||
Log.i(TAG, "Received image file with possible barcode");
|
||||
|
||||
Bitmap bitmap;
|
||||
try {
|
||||
bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), intent.getData());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error getting data from image file");
|
||||
e.printStackTrace();
|
||||
Toast.makeText(context, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
|
||||
return new BarcodeValues(null, null);
|
||||
}
|
||||
|
||||
BarcodeValues barcodeFromBitmap = getBarcodeFromBitmap(bitmap);
|
||||
|
||||
if (barcodeFromBitmap.isEmpty()) {
|
||||
Log.i(TAG, "No barcode found in image file");
|
||||
Toast.makeText(context, R.string.noBarcodeFound, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
Log.i(TAG, "Read barcode id: " + barcodeFromBitmap.content());
|
||||
Log.i(TAG, "Read format: " + barcodeFromBitmap.format());
|
||||
|
||||
return barcodeFromBitmap;
|
||||
}
|
||||
|
||||
if (requestCode == Utils.BARCODE_SCAN || requestCode == Utils.SELECT_BARCODE_REQUEST) {
|
||||
if (requestCode == Utils.BARCODE_SCAN) {
|
||||
Log.i(TAG, "Received barcode information from camera");
|
||||
} else if (requestCode == Utils.SELECT_BARCODE_REQUEST) {
|
||||
Log.i(TAG, "Received barcode information from typing it");
|
||||
} else {
|
||||
return new BarcodeValues(null, null);
|
||||
}
|
||||
|
||||
contents = intent.getStringExtra(BarcodeSelectorActivity.BARCODE_CONTENTS);
|
||||
format = intent.getStringExtra(BarcodeSelectorActivity.BARCODE_FORMAT);
|
||||
|
||||
Log.i(TAG, "Read barcode id: " + contents);
|
||||
Log.i(TAG, "Read format: " + format);
|
||||
|
||||
return new BarcodeValues(format, contents);
|
||||
}
|
||||
|
||||
Log.i(TAG, "Read barcode id: " + contents);
|
||||
Log.i(TAG, "Read format: " + format);
|
||||
throw new UnsupportedOperationException("Unknown request code for parseSetBarcodeActivityResult");
|
||||
}
|
||||
|
||||
return new BarcodeValues(format, contents);
|
||||
static public BarcodeValues getBarcodeFromBitmap(Bitmap bitmap) {
|
||||
// In order to decode it, the Bitmap must first be converted into a pixel array...
|
||||
int[] intArray = new int[bitmap.getWidth() * bitmap.getHeight()];
|
||||
bitmap.getPixels(intArray, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
|
||||
// ...and then turned into a binary bitmap from its luminance
|
||||
LuminanceSource source = new RGBLuminanceSource(bitmap.getWidth(), bitmap.getHeight(), intArray);
|
||||
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
|
||||
try {
|
||||
Result barcodeResult = new MultiFormatReader().decode(binaryBitmap);
|
||||
|
||||
return new BarcodeValues(barcodeResult.getBarcodeFormat().name(), barcodeResult.getText());
|
||||
} catch (NotFoundException e) {
|
||||
return new BarcodeValues(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
static public Boolean hasExpired(Date expiryDate) {
|
||||
|
||||
@@ -19,11 +19,25 @@
|
||||
app:zxing_viewfinder_laser="@color/zxing_custom_viewfinder_laser"
|
||||
app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_manually"
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/addManually"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:onClick="addManually"/>
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_from_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="addFromImage"
|
||||
android:text="@string/addFromImage" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_manually"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="addManually"
|
||||
android:text="@string/addManually" />
|
||||
</LinearLayout>
|
||||
</merge>
|
||||
@@ -135,6 +135,7 @@
|
||||
<string name="leaveWithoutSaveTitle">Leave without saving</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Are you sure you want to leave this screen? Changed made will not be saved.</string>
|
||||
<string name="addManually">Manually enter card ID</string>
|
||||
<string name="addFromImage">Select image from gallery</string>
|
||||
<string name="groupsList">Groups: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentence">Expires: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentenceExpired">Expired: <xliff:g>%s</xliff:g></string>
|
||||
@@ -150,6 +151,9 @@
|
||||
<string name="moveBarcodeToTopOfScreen">Move the barcode to the top of the screen</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">Center the barcode on the screen</string>
|
||||
|
||||
<string name="noBarcodeFound">No barcode was found</string>
|
||||
<string name="errorReadingImage">Error reading image</string>
|
||||
|
||||
<string name="balance">Balance</string>
|
||||
<string name="currency">Currency</string>
|
||||
<string name="points">Points</string>
|
||||
|
||||
Reference in New Issue
Block a user