diff --git a/app/src/main/java/protect/card_locker/ScanActivity.java b/app/src/main/java/protect/card_locker/ScanActivity.java index fea6db1cf..f2b7ef135 100644 --- a/app/src/main/java/protect/card_locker/ScanActivity.java +++ b/app/src/main/java/protect/card_locker/ScanActivity.java @@ -67,6 +67,7 @@ public class ScanActivity extends CatimaAppCompatActivity { private static final int PERMISSION_SCAN_ADD_FROM_IMAGE = 100; private static final int PERMISSION_SCAN_ADD_FROM_PDF = 101; + private static final int PERMISSION_SCAN_ADD_FROM_PKPASS = 102; private CaptureManager capture; private DecoratedBarcodeView barcodeScannerView; @@ -79,6 +80,7 @@ public class ScanActivity extends CatimaAppCompatActivity { // can't use the pre-made contract because that launches the file manager for image type instead of gallery private ActivityResultLauncher photoPickerLauncher; private ActivityResultLauncher pdfPickerLauncher; + private ActivityResultLauncher pkpassPickerLauncher; static final String STATE_SCANNER_ACTIVE = "scannerActive"; private boolean mScannerActive = true; @@ -107,6 +109,7 @@ public class ScanActivity extends CatimaAppCompatActivity { manualAddLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.SELECT_BARCODE_REQUEST, result.getResultCode(), result.getData())); photoPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_IMAGE_FILE, result.getResultCode(), result.getData())); pdfPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_PDF_FILE, result.getResultCode(), result.getData())); + pkpassPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_PKPASS_FILE, result.getResultCode(), result.getData())); customBarcodeScannerBinding.fabOtherOptions.setOnClickListener(view -> { setScannerActive(false); @@ -116,12 +119,14 @@ public class ScanActivity extends CatimaAppCompatActivity { getString(R.string.addManually), getString(R.string.addFromImage), getString(R.string.addFromPdfFile), + getString(R.string.addFromPkpass) }; Object[] icons = new Object[]{ R.drawable.baseline_block_24, R.drawable.ic_edit, R.drawable.baseline_image_24, R.drawable.baseline_picture_as_pdf_24, + R.drawable.local_activity_24px }; String[] columns = new String[]{"text", "icon"}; @@ -158,6 +163,9 @@ public class ScanActivity extends CatimaAppCompatActivity { case 3: addFromPdf(); break; + case 4: + addFromPkPass(); + break; default: throw new IllegalArgumentException("Unknown 'Add a card in a different way' dialog option"); } @@ -415,6 +423,10 @@ public class ScanActivity extends CatimaAppCompatActivity { PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_PDF); } + public void addFromPkPass() { + PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_PKPASS); + } + private void addFromImageOrFileAfterPermission(String mimeType, ActivityResultLauncher launcher, int chooserText, int errorMessage) { Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType(mimeType); @@ -504,12 +516,14 @@ public class ScanActivity extends CatimaAppCompatActivity { } else { showCameraPermissionMissingText(); } - } else if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE || requestCode == PERMISSION_SCAN_ADD_FROM_PDF) { + } else if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE || requestCode == PERMISSION_SCAN_ADD_FROM_PDF || requestCode == PERMISSION_SCAN_ADD_FROM_PKPASS) { if (granted) { if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE) { addFromImageOrFileAfterPermission("image/*", photoPickerLauncher, R.string.addFromImage, R.string.failedLaunchingPhotoPicker); - } else { + } else if (requestCode == PERMISSION_SCAN_ADD_FROM_PDF) { addFromImageOrFileAfterPermission("application/pdf", pdfPickerLauncher, R.string.addFromPdfFile, R.string.failedLaunchingFileManager); + } else { + addFromImageOrFileAfterPermission("application/*", pkpassPickerLauncher, R.string.addFromPkpass, R.string.failedLaunchingFileManager); } } else { setScannerActive(true); diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java index 349174c0e..4fb9e1441 100644 --- a/app/src/main/java/protect/card_locker/Utils.java +++ b/app/src/main/java/protect/card_locker/Utils.java @@ -97,12 +97,13 @@ public class Utils { public static final int BARCODE_SCAN = 3; public static final int BARCODE_IMPORT_FROM_IMAGE_FILE = 4; public static final int BARCODE_IMPORT_FROM_PDF_FILE = 5; - public static final int CARD_IMAGE_FROM_CAMERA_FRONT = 6; - public static final int CARD_IMAGE_FROM_CAMERA_BACK = 7; - public static final int CARD_IMAGE_FROM_CAMERA_ICON = 8; - public static final int CARD_IMAGE_FROM_FILE_FRONT = 9; - public static final int CARD_IMAGE_FROM_FILE_BACK = 10; - public static final int CARD_IMAGE_FROM_FILE_ICON = 11; + public static final int BARCODE_IMPORT_FROM_PKPASS_FILE = 6; + public static final int CARD_IMAGE_FROM_CAMERA_FRONT = 7; + public static final int CARD_IMAGE_FROM_CAMERA_BACK = 8; + public static final int CARD_IMAGE_FROM_CAMERA_ICON = 9; + public static final int CARD_IMAGE_FROM_FILE_FRONT = 10; + public static final int CARD_IMAGE_FROM_FILE_BACK = 11; + public static final int CARD_IMAGE_FROM_FILE_ICON = 12; public static final String CARD_IMAGE_FILENAME_REGEX = "^(card_)(\\d+)(_(?:front|back|icon)\\.png)$"; @@ -174,6 +175,32 @@ public class Utils { return barcodesFromBitmap; } + static public List retrieveBarcodesFromPkPass(Context context, Uri uri) { + // FIXME: Also return image + Log.i(TAG, "Received Pkpass file with possible barcode"); + if (uri == null) { + Log.e(TAG, "Pkpass did not contain any data"); + Toast.makeText(context, R.string.errorReadingFile, Toast.LENGTH_LONG).show(); + return null; + } + + PkpassParser pkpassParser = new PkpassParser(context, uri); + + List locales = pkpassParser.listLocales(); + if (locales.isEmpty()) { + return Collections.singletonList(new ParseResult(ParseResultType.FULL, pkpassParser.toLoyaltyCard(null))); + } + + List parseResultList = new ArrayList<>(); + for (String locale : locales) { + ParseResult parseResult = new ParseResult(ParseResultType.FULL, pkpassParser.toLoyaltyCard(locale)); + parseResult.setNote(locale); + parseResultList.add(parseResult); + } + + return parseResultList; + } + static public List retrieveBarcodesFromPdf(Context context, Uri uri) { Log.i(TAG, "Received PDF file with possible barcode"); if (uri == null) { @@ -264,6 +291,10 @@ public class Utils { return retrieveBarcodesFromPdf(context, intent.getData()); } + if (requestCode == Utils.BARCODE_IMPORT_FROM_PKPASS_FILE) { + return retrieveBarcodesFromPkPass(context, intent.getData()); + } + if (requestCode == Utils.BARCODE_SCAN || requestCode == Utils.SELECT_BARCODE_REQUEST) { if (requestCode == Utils.BARCODE_SCAN) { Log.i(TAG, "Received barcode information from camera"); diff --git a/app/src/main/res/drawable/local_activity_24px.xml b/app/src/main/res/drawable/local_activity_24px.xml new file mode 100644 index 000000000..21c31ee00 --- /dev/null +++ b/app/src/main/res/drawable/local_activity_24px.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fe94854b8..881eccf1f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -360,5 +360,6 @@ Export cancelled Use front image Use back image + Select a Passbook file (.pkpass) This file is not supported