Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera permission behaviour #505

Merged
merged 14 commits into from
Jan 7, 2020
8 changes: 8 additions & 0 deletions sample/src/main/java/example/zxing/CustomScannerActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import android.view.View;
import android.widget.Button;

import androidx.annotation.NonNull;

import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
import com.journeyapps.barcodescanner.ViewfinderView;
Expand Down Expand Up @@ -45,6 +47,7 @@ protected void onCreate(Bundle savedInstanceState) {

capture = new CaptureManager(this, barcodeScannerView);
capture.initializeFromIntent(getIntent(), savedInstanceState);
capture.setShowMissingCameraPermissionDialog(false);
capture.decode();

changeMaskColor(null);
Expand Down Expand Up @@ -116,4 +119,9 @@ public void onTorchOn() {
public void onTorchOff() {
switchFlashlightButton.setText(R.string.turn_on_flashlight);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
capture.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
10 changes: 8 additions & 2 deletions sample/src/main/java/example/zxing/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,14 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(resultCode, data);

if(result.getContents() == null) {
Log.d("MainActivity", "Cancelled scan");
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
Intent originalIntent = result.getOriginalIntent();
if (originalIntent == null) {
Log.d("MainActivity", "Cancelled scan");
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else if(originalIntent.hasExtra(Intents.Scan.MISSING_CAMERA_PERMISSION)) {
Log.d("MainActivity", "Cancelled scan due to missing camera permission");
Toast.makeText(this, "Cancelled due to missing camera permission", Toast.LENGTH_LONG).show();
}
} else {
Log.d("MainActivity", "Scanned");
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ public static final class Scan {
*/
public static final String TIMEOUT = "TIMEOUT";

/**
* Set the time to finish the scan screen.
*/
public static final String MISSING_CAMERA_PERMISSION = "MISSING_CAMERA_PERMISSION";

/**
* Set the time to finish the scan screen.
*/
public static final String SHOW_MISSING_CAMERA_PERMISSION_DIALOG = "SHOW_MISSING_CAMERA_PERMISSION_DIALOG";

/**
* Set the time to finish the scan screen.
*/
public static final String MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE = "MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE";

/**
* Whether or not the orientation should be locked when the activity is first started.
* Defaults to true.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,9 +383,10 @@ public static IntentResult parseActivityResult(int resultCode, Intent intent) {
rawBytes,
orientation,
errorCorrectionLevel,
barcodeImagePath);
barcodeImagePath,
intent);
}
return new IntentResult();
return new IntentResult(intent);
}

private static List<String> list(String... values) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.google.zxing.integration.android;

import android.content.Intent;

/**
* <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
*
Expand All @@ -29,23 +31,30 @@ public final class IntentResult {
private final Integer orientation;
private final String errorCorrectionLevel;
private final String barcodeImagePath;
private final Intent originalIntent;

IntentResult() {
this(null, null, null, null, null, null);
this(null, null, null, null, null, null, null);
}

IntentResult(Intent intent) {
this(null, null, null, null, null, null, intent);
}

IntentResult(String contents,
String formatName,
byte[] rawBytes,
Integer orientation,
String errorCorrectionLevel,
String barcodeImagePath) {
String barcodeImagePath,
Intent originalIntent) {
this.contents = contents;
this.formatName = formatName;
this.rawBytes = rawBytes;
this.orientation = orientation;
this.errorCorrectionLevel = errorCorrectionLevel;
this.barcodeImagePath = barcodeImagePath;
this.originalIntent = originalIntent;
}

/**
Expand Down Expand Up @@ -90,6 +99,13 @@ public String getBarcodeImagePath() {
return barcodeImagePath;
}

/**
* @return the original intent
*/
public Intent getOriginalIntent() {
return originalIntent;
}

@Override
public String toString() {
int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
Expand All @@ -98,6 +114,7 @@ public String toString() {
"Raw bytes: (" + rawBytesLength + " bytes)\n" +
"Orientation: " + orientation + '\n' +
"EC level: " + errorCorrectionLevel + '\n' +
"Barcode image: " + barcodeImagePath + '\n';
"Barcode image: " + barcodeImagePath + '\n' +
"Original intent: " + originalIntent + '\n';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
Expand All @@ -13,14 +12,15 @@
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.Window;
import android.view.WindowManager;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.google.zxing.ResultMetadataType;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.BeepManager;
Expand Down Expand Up @@ -61,6 +61,9 @@ public class CaptureManager {
private static final String SAVED_ORIENTATION_LOCK = "SAVED_ORIENTATION_LOCK";
private boolean returnBarcodeImagePath = false;

private boolean showDialogIfMissingCameraPermission = true;
private String missingCameraPermissionDialogMessage = "";

private boolean destroyed = false;

private InactivityTimer inactivityTimer;
Expand Down Expand Up @@ -109,7 +112,9 @@ public void previewStopped() {

@Override
public void cameraError(Exception error) {
displayFrameworkBugMessageAndExit();
displayFrameworkBugMessageAndExit(
activity.getString(R.string.zxing_msg_camera_framework_bug)
);
}

@Override
Expand Down Expand Up @@ -171,6 +176,13 @@ public void initializeFromIntent(Intent intent, Bundle savedInstanceState) {
beepManager.setBeepEnabled(false);
}

if (intent.hasExtra(Intents.Scan.SHOW_MISSING_CAMERA_PERMISSION_DIALOG)) {
setShowMissingCameraPermissionDialog(
intent.getBooleanExtra(Intents.Scan.SHOW_MISSING_CAMERA_PERMISSION_DIALOG, true),
intent.getStringExtra(Intents.Scan.MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE)
);
}

if (intent.hasExtra(Intents.Scan.TIMEOUT)) {
Runnable runnable = new Runnable() {
@Override
Expand Down Expand Up @@ -249,9 +261,7 @@ private void openCameraWithPermission() {
new String[]{Manifest.permission.CAMERA},
cameraPermissionReqCode);
askedPermission = true;
} else {
// Wait for permission result
}
} // else wait for permission result
}

/**
Expand All @@ -268,8 +278,13 @@ public void onRequestPermissionsResult(int requestCode, String permissions[], in
// permission was granted
barcodeView.resume();
} else {
// TODO: display better error message.
displayFrameworkBugMessageAndExit();
setMissingCameraPermissionResult();

if (showDialogIfMissingCameraPermission) {
displayFrameworkBugMessageAndExit(missingCameraPermissionDialogMessage);
} else {
closeAndFinish();
}
}
}
}
Expand Down Expand Up @@ -384,6 +399,12 @@ protected void closeAndFinish() {
inactivityTimer.cancel();
}

private void setMissingCameraPermissionResult() {
Intent intent = new Intent(Intents.Scan.ACTION);
intent.putExtra(Intents.Scan.MISSING_CAMERA_PERMISSION, true);
activity.setResult(Activity.RESULT_CANCELED, intent);
}

protected void returnResultTimeout() {
Intent intent = new Intent(Intents.Scan.ACTION);
intent.putExtra(Intents.Scan.TIMEOUT, true);
Expand All @@ -397,25 +418,20 @@ protected void returnResult(BarcodeResult rawResult) {
closeAndFinish();
}

protected void displayFrameworkBugMessageAndExit() {
protected void displayFrameworkBugMessageAndExit(String message) {
if (activity.isFinishing() || this.destroyed || finishWhenClosed) {
return;
}

if (message.isEmpty()) {
message = activity.getString(R.string.zxing_msg_camera_framework_bug);
}

AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(activity.getString(R.string.zxing_app_name));
builder.setMessage(activity.getString(R.string.zxing_msg_camera_framework_bug));
builder.setPositiveButton(R.string.zxing_button_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
builder.setMessage(message);
builder.setPositiveButton(R.string.zxing_button_ok, (dialog, which) -> finish());
builder.setOnCancelListener(dialog -> finish());
builder.show();
}

Expand All @@ -426,4 +442,29 @@ public static int getCameraPermissionReqCode() {
public static void setCameraPermissionReqCode(int cameraPermissionReqCode) {
CaptureManager.cameraPermissionReqCode = cameraPermissionReqCode;
}

/**
* If set to true, shows the default error dialog if camera permission is missing.
* <p>
* If set to false, instead the capture manager just finishes.
* <p>
* In both cases, the activity result is set to {@link Intents.Scan#MISSING_CAMERA_PERMISSION}
* and cancelled
*/
public void setShowMissingCameraPermissionDialog(boolean visible) {
setShowMissingCameraPermissionDialog(visible, "");
}

/**
* If set to true, shows the specified error dialog message if camera permission is missing.
* <p>
* If set to false, instead the capture manager just finishes.
* <p>
* In both cases, the activity result is set to {@link Intents.Scan#MISSING_CAMERA_PERMISSION}
* and cancelled
*/
public void setShowMissingCameraPermissionDialog(boolean visible, String message) {
showDialogIfMissingCameraPermission = visible;
missingCameraPermissionDialogMessage = message != null ? message : "";
}
}