From 1e8a43a6ca0e5ee37aaad24dad641942048b7edd Mon Sep 17 00:00:00 2001 From: Daniel Ziegenberg Date: Tue, 16 Mar 2021 23:01:14 +0100 Subject: [PATCH 1/3] Add Copyright Notice Signed-off-by: Daniel Ziegenberg --- .../andotp/Utilities/ScanQRCodeFromFile.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/ScanQRCodeFromFile.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/ScanQRCodeFromFile.java index 242e0b4b..78b14aef 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/ScanQRCodeFromFile.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/ScanQRCodeFromFile.java @@ -1,3 +1,26 @@ +/* + * Copyright (C) 2017-2020 Jakob Nixdorf + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + package org.shadowice.flocke.andotp.Utilities; import android.content.Context; From ff9c9c6a8f536d9f07c02c804b482185328b0cd6 Mon Sep 17 00:00:00 2001 From: Daniel Ziegenberg Date: Tue, 16 Mar 2021 23:07:36 +0100 Subject: [PATCH 2/3] Make reading QR codes more robust - use QRCodeReader instead of MultiFormatReader - use decoding hints with BarcodeFormat.QR_CODE - try a second time with DecodeHintType.TRY_HARDER Signed-off-by: Daniel Ziegenberg --- .../andotp/Utilities/ScanQRCodeFromFile.java | 84 +++++++++++++++---- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/ScanQRCodeFromFile.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/ScanQRCodeFromFile.java index 78b14aef..cc4c0550 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/ScanQRCodeFromFile.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/ScanQRCodeFromFile.java @@ -29,21 +29,44 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.widget.Toast; +import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.ChecksumException; +import com.google.zxing.DecodeHintType; import com.google.zxing.FormatException; import com.google.zxing.LuminanceSource; -import com.google.zxing.MultiFormatReader; import com.google.zxing.NotFoundException; import com.google.zxing.RGBLuminanceSource; -import com.google.zxing.Reader; +import com.google.zxing.ReaderException; import com.google.zxing.Result; import com.google.zxing.common.HybridBinarizer; +import com.google.zxing.qrcode.QRCodeReader; import org.shadowice.flocke.andotp.R; + import java.io.IOException; +import java.util.EnumMap; +import java.util.Map; +import java.util.Vector; public class ScanQRCodeFromFile { + + private static final Map HINTS; + + private static final Map HINTS_HARDER; + + static { + Vector barcodeFormats = new Vector<>(); + barcodeFormats.add(BarcodeFormat.QR_CODE); + + HINTS = new EnumMap<>(DecodeHintType.class); + HINTS.put(DecodeHintType.POSSIBLE_FORMATS, barcodeFormats); + + HINTS_HARDER = new EnumMap<>(HINTS); + HINTS_HARDER.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); + } + + public static String scanQRImage(Context context, Uri uri) { //Check if external storage is accessible if (!Tools.isExternalStorageReadable()) { @@ -53,35 +76,60 @@ public class ScanQRCodeFromFile { //Get image in bytes byte[] imageInBytes; try { - imageInBytes = StorageAccessHelper.loadFile(context,uri); + imageInBytes = StorageAccessHelper.loadFile(context, uri); } catch (IOException e) { e.printStackTrace(); - Toast.makeText(context,R.string.toast_file_load_error,Toast.LENGTH_LONG).show(); + Toast.makeText(context, R.string.toast_file_load_error, Toast.LENGTH_LONG).show(); return null; } - Bitmap bMap = BitmapFactory.decodeByteArray(imageInBytes,0,imageInBytes.length); + Bitmap bMap = BitmapFactory.decodeByteArray(imageInBytes, 0, imageInBytes.length); String contents = null; - int[] intArray = new int[bMap.getWidth()*bMap.getHeight()]; + int[] intArray = new int[bMap.getWidth() * bMap.getHeight()]; bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight()); LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(), intArray); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); - Reader reader = new MultiFormatReader(); - //Try finding QR code + + Result result = null; + + + QRCodeReader reader = new QRCodeReader(); + ReaderException savedException = null; + try { - Result result = reader.decode(bitmap); + //Try finding QR code + result = reader.decode(bitmap, HINTS); contents = result.getText(); - } catch (NotFoundException e) { - e.printStackTrace(); - Toast.makeText(context,R.string.toast_qr_error,Toast.LENGTH_LONG).show(); - } catch (ChecksumException e) { - e.printStackTrace(); - Toast.makeText(context,R.string.toast_qr_checksum_exception,Toast.LENGTH_LONG).show(); - } catch (FormatException e) { - e.printStackTrace(); - Toast.makeText(context,R.string.toast_qr_format_error,Toast.LENGTH_LONG).show(); + } catch (ReaderException re) { + savedException = re; } + + if (contents == null) { + try { + //Try finding QR code really hard + result = reader.decode(bitmap, HINTS_HARDER); + contents = result.getText(); + } catch (ReaderException re) { + savedException = re; + } + } + + if (contents == null) { + try { + throw savedException == null ? NotFoundException.getNotFoundInstance() : savedException; + } catch (ChecksumException e) { + e.printStackTrace(); + Toast.makeText(context, R.string.toast_qr_checksum_exception, Toast.LENGTH_LONG).show(); + } catch (FormatException e) { + e.printStackTrace(); + Toast.makeText(context, R.string.toast_qr_format_error, Toast.LENGTH_LONG).show(); + } catch (ReaderException e) { // Including NotFoundException + e.printStackTrace(); + Toast.makeText(context, R.string.toast_qr_error, Toast.LENGTH_LONG).show(); + } + } + //Return QR code (if found) return contents; } From c43d7c08bd74f34246572123abd884b544345de4 Mon Sep 17 00:00:00 2001 From: Daniel Ziegenberg Date: Tue, 16 Mar 2021 23:10:17 +0100 Subject: [PATCH 3/3] Update dependency ZXing - update com.google.zxing:core to 3.4.1 Signed-off-by: Daniel Ziegenberg --- app/build.gradle | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index be24885c..143ff827 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -72,12 +72,7 @@ dependencies { implementation "com.github.aakira:expandable-layout:1.6.0" implementation "com.heinrichreimersoftware:material-intro:2.0.0" implementation("com.journeyapps:zxing-android-embedded:4.1.0") { transitive = false } - implementation('com.google.zxing:core') { - version { - strictly '[3.3, 3.4[' // Keep pinned below 3.4 to support SDK versions below 24 - prefer '3.3.0' - } - } + implementation('com.google.zxing:core:3.4.1') implementation "com.vanniktech:vntnumberpickerpreference:1.0.0" implementation "me.zhanghai.android.materialprogressbar:library:1.6.1" implementation "org.sufficientlysecure:openpgp-api:12.0"