diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 53861ab0e..f783db266 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -16,7 +16,7 @@
+ android:required="false" />
diff --git a/app/src/main/java/protect/card_locker/CatimaCaptureManager.java b/app/src/main/java/protect/card_locker/CatimaCaptureManager.java
index 7507d8090..e083c48ff 100644
--- a/app/src/main/java/protect/card_locker/CatimaCaptureManager.java
+++ b/app/src/main/java/protect/card_locker/CatimaCaptureManager.java
@@ -4,22 +4,24 @@ import android.app.Activity;
import android.content.Context;
import android.widget.Toast;
+import androidx.core.util.Consumer;
+
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
public class CatimaCaptureManager extends CaptureManager {
- private final Context mContext;
+ private final Consumer mErrorCallback;
- public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
+ public CatimaCaptureManager(Activity activity, DecoratedBarcodeView barcodeView, Consumer errorCallback) {
super(activity, barcodeView);
- mContext = activity.getApplicationContext();
+ mErrorCallback = errorCallback;
}
@Override
protected void displayFrameworkBugMessageAndExit(String message) {
// We don't want to exit, as we also have a enter from card image and add manually button here
- // So we show a toast instead
- Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
+ // So, instead, we call our error callback
+ mErrorCallback.accept(message);
}
}
diff --git a/app/src/main/java/protect/card_locker/ScanActivity.java b/app/src/main/java/protect/card_locker/ScanActivity.java
index 9679751bb..9c177751e 100644
--- a/app/src/main/java/protect/card_locker/ScanActivity.java
+++ b/app/src/main/java/protect/card_locker/ScanActivity.java
@@ -78,6 +78,7 @@ public class ScanActivity extends CatimaAppCompatActivity {
static final String STATE_SCANNER_ACTIVE = "scannerActive";
private boolean mScannerActive = true;
+ private boolean mHasError = false;
private void extractIntentFields(Intent intent) {
final Bundle b = intent.getExtras();
@@ -141,7 +142,7 @@ public class ScanActivity extends CatimaAppCompatActivity {
// Even though we do the actual decoding with the barcodeScannerView
// CaptureManager needs to be running to show the camera and scanning bar
- capture = new CatimaCaptureManager(this, barcodeScannerView);
+ capture = new CatimaCaptureManager(this, barcodeScannerView, this::onCaptureManagerError);
Intent captureIntent = new Intent();
Bundle captureIntentBundle = new Bundle();
captureIntentBundle.putBoolean(Intents.Scan.BEEP_ENABLED, false);
@@ -178,9 +179,14 @@ public class ScanActivity extends CatimaAppCompatActivity {
capture.onResume();
}
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
- showCameraPermissionMissingText(false);
+ if (!Utils.deviceHasCamera(this)) {
+ showCameraError(getString(R.string.noCameraFoundGuideText), false);
+ } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
+ showCameraPermissionMissingText();
+ } else {
+ hideCameraError();
}
+
scaleScreen();
}
@@ -402,12 +408,37 @@ public class ScanActivity extends CatimaAppCompatActivity {
}
}
- private void showCameraPermissionMissingText(boolean show) {
- customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedClickableArea.setOnClickListener(show ? v -> {
+ public void onCaptureManagerError(String errorMessage) {
+ if (mHasError) {
+ // We're already showing an error, ignore this new error
+ return;
+ }
+
+ showCameraError(errorMessage, false);
+ }
+
+ private void showCameraPermissionMissingText() {
+ showCameraError(getString(R.string.noCameraPermissionDirectToSystemSetting), true);
+ }
+
+ private void showCameraError(String message, boolean setOnClick) {
+ customBarcodeScannerBinding.cameraErrorLayout.cameraErrorMessage.setText(message);
+
+ setCameraErrorState(true, setOnClick);
+ }
+
+ private void hideCameraError() {
+ setCameraErrorState(false, false);
+ }
+
+ private void setCameraErrorState(boolean visible, boolean setOnClick) {
+ mHasError = visible;
+
+ customBarcodeScannerBinding.cameraErrorLayout.cameraErrorClickableArea.setOnClickListener(visible && setOnClick ? v -> {
navigateToSystemPermissionSetting();
} : null);
- customBarcodeScannerBinding.cardInputContainer.setBackgroundColor(show ? obtainThemeAttribute(com.google.android.material.R.attr.colorSurface) : Color.TRANSPARENT);
- customBarcodeScannerBinding.cameraPermissionDeniedLayout.getRoot().setVisibility(show ? View.VISIBLE : View.GONE);
+ customBarcodeScannerBinding.cardInputContainer.setBackgroundColor(visible ? obtainThemeAttribute(com.google.android.material.R.attr.colorSurface) : Color.TRANSPARENT);
+ customBarcodeScannerBinding.cameraErrorLayout.getRoot().setVisibility(visible ? View.VISIBLE : View.GONE);
}
private void scaleScreen() {
@@ -417,8 +448,8 @@ public class ScanActivity extends CatimaAppCompatActivity {
float mediumSizePx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,MEDIUM_SCALE_FACTOR_DIP,getResources().getDisplayMetrics());
boolean shouldScaleSmaller = screenHeight < mediumSizePx;
- customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedIcon.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
- customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedTitle.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
+ customBarcodeScannerBinding.cameraErrorLayout.cameraErrorIcon.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
+ customBarcodeScannerBinding.cameraErrorLayout.cameraErrorTitle.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
}
private int obtainThemeAttribute(int attribute) {
@@ -444,7 +475,11 @@ public class ScanActivity extends CatimaAppCompatActivity {
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (requestCode == CaptureManager.getCameraPermissionReqCode()) {
- showCameraPermissionMissingText(!granted);
+ if (granted) {
+ hideCameraError();
+ } else {
+ showCameraPermissionMissingText();
+ }
} else if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE || requestCode == PERMISSION_SCAN_ADD_FROM_PDF) {
if (granted) {
if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE) {
diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java
index 7402468b9..eb3ef6bf1 100644
--- a/app/src/main/java/protect/card_locker/Utils.java
+++ b/app/src/main/java/protect/card_locker/Utils.java
@@ -13,6 +13,8 @@ import android.graphics.Color;
import android.graphics.ImageDecoder;
import android.graphics.Matrix;
import android.graphics.pdf.PdfRenderer;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraManager;
import android.net.Uri;
import android.os.Build;
import android.os.ParcelFileDescriptor;
@@ -1015,4 +1017,12 @@ public class Utils {
return false;
});
}
+
+ public static boolean deviceHasCamera(Context context) {
+ try {
+ return ((CameraManager) context.getSystemService(Context.CAMERA_SERVICE)).getCameraIdList().length > 0;
+ } catch (CameraAccessException e) {
+ return false;
+ }
+ }
}
diff --git a/app/src/main/res/drawable/camera_permission_denied.xml b/app/src/main/res/drawable/camera_error.xml
similarity index 100%
rename from app/src/main/res/drawable/camera_permission_denied.xml
rename to app/src/main/res/drawable/camera_error.xml
diff --git a/app/src/main/res/layout/camera_permission_failed_layout.xml b/app/src/main/res/layout/camera_error_layout.xml
similarity index 76%
rename from app/src/main/res/layout/camera_permission_failed_layout.xml
rename to app/src/main/res/layout/camera_error_layout.xml
index 2d47929a6..8e3d823ea 100644
--- a/app/src/main/res/layout/camera_permission_failed_layout.xml
+++ b/app/src/main/res/layout/camera_error_layout.xml
@@ -9,20 +9,20 @@
tools:showIn="@layout/custom_barcode_scanner">
+ android:src="@drawable/camera_error" />
+ android:text="@string/zxing_msg_camera_framework_bug" />
diff --git a/app/src/main/res/layout/custom_barcode_scanner.xml b/app/src/main/res/layout/custom_barcode_scanner.xml
index d197ffde5..3ab8c96a0 100644
--- a/app/src/main/res/layout/custom_barcode_scanner.xml
+++ b/app/src/main/res/layout/custom_barcode_scanner.xml
@@ -34,8 +34,8 @@
android:padding="@dimen/activity_scanner_padding">
Could not find a supported file manager
Which of the found barcodes do you want to use?
Page %d
+ Your device does not seem to have a camera. If it does, try rebooting the device. Otherwise, use the "More options" button below to add a barcode another way.