Skip to content

Commit e0d3409

Browse files
Andre Ippischrkistner
authored andcommitted
Camera permission behaviour (#505)
* Remove unused else * Remove SDK version check since we are on minimum 24 already * Add intent key about missing camera permission * Add boolean value to show error dialog - always true for the beginning to keep current behaviour * Make displaying an error dialog for missing camera permissions optional * Add intent extras for Intent initialisation * Initialise camera permission dialog visibility from Intent * Add original intent to IntentResult * Use original intent in IntentResult * Make onRequestPermissionResult public again * Forward onRequestPermissionResult * React on Intent information - for example on the missing camera permission * Revert "Remove SDK version check since we are on minimum 24 already" This reverts commit 8f79f56 * Add missing imports
1 parent 9b924e6 commit e0d3409

File tree

6 files changed

+118
-30
lines changed

6 files changed

+118
-30
lines changed

sample/src/main/java/example/zxing/CustomScannerActivity.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import android.view.View;
99
import android.widget.Button;
1010

11+
import androidx.annotation.NonNull;
12+
1113
import com.journeyapps.barcodescanner.CaptureManager;
1214
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
1315
import com.journeyapps.barcodescanner.ViewfinderView;
@@ -45,6 +47,7 @@ protected void onCreate(Bundle savedInstanceState) {
4547

4648
capture = new CaptureManager(this, barcodeScannerView);
4749
capture.initializeFromIntent(getIntent(), savedInstanceState);
50+
capture.setShowMissingCameraPermissionDialog(false);
4851
capture.decode();
4952

5053
changeMaskColor(null);
@@ -116,4 +119,9 @@ public void onTorchOn() {
116119
public void onTorchOff() {
117120
switchFlashlightButton.setText(R.string.turn_on_flashlight);
118121
}
122+
123+
@Override
124+
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
125+
capture.onRequestPermissionsResult(requestCode, permissions, grantResults);
126+
}
119127
}

sample/src/main/java/example/zxing/MainActivity.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,14 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
128128
IntentResult result = IntentIntegrator.parseActivityResult(resultCode, data);
129129

130130
if(result.getContents() == null) {
131-
Log.d("MainActivity", "Cancelled scan");
132-
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
131+
Intent originalIntent = result.getOriginalIntent();
132+
if (originalIntent == null) {
133+
Log.d("MainActivity", "Cancelled scan");
134+
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
135+
} else if(originalIntent.hasExtra(Intents.Scan.MISSING_CAMERA_PERMISSION)) {
136+
Log.d("MainActivity", "Cancelled scan due to missing camera permission");
137+
Toast.makeText(this, "Cancelled due to missing camera permission", Toast.LENGTH_LONG).show();
138+
}
133139
} else {
134140
Log.d("MainActivity", "Scanned");
135141
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();

zxing-android-embedded/src/com/google/zxing/client/android/Intents.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,21 @@ public static final class Scan {
115115
*/
116116
public static final String TIMEOUT = "TIMEOUT";
117117

118+
/**
119+
* Set the time to finish the scan screen.
120+
*/
121+
public static final String MISSING_CAMERA_PERMISSION = "MISSING_CAMERA_PERMISSION";
122+
123+
/**
124+
* Set the time to finish the scan screen.
125+
*/
126+
public static final String SHOW_MISSING_CAMERA_PERMISSION_DIALOG = "SHOW_MISSING_CAMERA_PERMISSION_DIALOG";
127+
128+
/**
129+
* Set the time to finish the scan screen.
130+
*/
131+
public static final String MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE = "MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE";
132+
118133
/**
119134
* Whether or not the orientation should be locked when the activity is first started.
120135
* Defaults to true.

zxing-android-embedded/src/com/google/zxing/integration/android/IntentIntegrator.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,9 +383,10 @@ public static IntentResult parseActivityResult(int resultCode, Intent intent) {
383383
rawBytes,
384384
orientation,
385385
errorCorrectionLevel,
386-
barcodeImagePath);
386+
barcodeImagePath,
387+
intent);
387388
}
388-
return new IntentResult();
389+
return new IntentResult(intent);
389390
}
390391

391392
private static List<String> list(String... values) {

zxing-android-embedded/src/com/google/zxing/integration/android/IntentResult.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package com.google.zxing.integration.android;
1818

19+
import android.content.Intent;
20+
1921
/**
2022
* <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
2123
*
@@ -29,23 +31,30 @@ public final class IntentResult {
2931
private final Integer orientation;
3032
private final String errorCorrectionLevel;
3133
private final String barcodeImagePath;
34+
private final Intent originalIntent;
3235

3336
IntentResult() {
34-
this(null, null, null, null, null, null);
37+
this(null, null, null, null, null, null, null);
38+
}
39+
40+
IntentResult(Intent intent) {
41+
this(null, null, null, null, null, null, intent);
3542
}
3643

3744
IntentResult(String contents,
3845
String formatName,
3946
byte[] rawBytes,
4047
Integer orientation,
4148
String errorCorrectionLevel,
42-
String barcodeImagePath) {
49+
String barcodeImagePath,
50+
Intent originalIntent) {
4351
this.contents = contents;
4452
this.formatName = formatName;
4553
this.rawBytes = rawBytes;
4654
this.orientation = orientation;
4755
this.errorCorrectionLevel = errorCorrectionLevel;
4856
this.barcodeImagePath = barcodeImagePath;
57+
this.originalIntent = originalIntent;
4958
}
5059

5160
/**
@@ -90,6 +99,13 @@ public String getBarcodeImagePath() {
9099
return barcodeImagePath;
91100
}
92101

102+
/**
103+
* @return the original intent
104+
*/
105+
public Intent getOriginalIntent() {
106+
return originalIntent;
107+
}
108+
93109
@Override
94110
public String toString() {
95111
int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
@@ -98,6 +114,7 @@ public String toString() {
98114
"Raw bytes: (" + rawBytesLength + " bytes)\n" +
99115
"Orientation: " + orientation + '\n' +
100116
"EC level: " + errorCorrectionLevel + '\n' +
101-
"Barcode image: " + barcodeImagePath + '\n';
117+
"Barcode image: " + barcodeImagePath + '\n' +
118+
"Original intent: " + originalIntent + '\n';
102119
}
103120
}

zxing-android-embedded/src/com/journeyapps/barcodescanner/CaptureManager.java

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import android.annotation.TargetApi;
55
import android.app.Activity;
66
import android.app.AlertDialog;
7-
import android.content.DialogInterface;
87
import android.content.Intent;
98
import android.content.pm.ActivityInfo;
109
import android.content.pm.PackageManager;
@@ -13,14 +12,15 @@
1312
import android.os.Build;
1413
import android.os.Bundle;
1514
import android.os.Handler;
16-
import androidx.core.app.ActivityCompat;
17-
import androidx.core.content.ContextCompat;
1815
import android.util.Log;
1916
import android.view.Display;
2017
import android.view.Surface;
2118
import android.view.Window;
2219
import android.view.WindowManager;
2320

21+
import androidx.core.app.ActivityCompat;
22+
import androidx.core.content.ContextCompat;
23+
2424
import com.google.zxing.ResultMetadataType;
2525
import com.google.zxing.ResultPoint;
2626
import com.google.zxing.client.android.BeepManager;
@@ -61,6 +61,9 @@ public class CaptureManager {
6161
private static final String SAVED_ORIENTATION_LOCK = "SAVED_ORIENTATION_LOCK";
6262
private boolean returnBarcodeImagePath = false;
6363

64+
private boolean showDialogIfMissingCameraPermission = true;
65+
private String missingCameraPermissionDialogMessage = "";
66+
6467
private boolean destroyed = false;
6568

6669
private InactivityTimer inactivityTimer;
@@ -103,7 +106,9 @@ public void previewStopped() {
103106

104107
@Override
105108
public void cameraError(Exception error) {
106-
displayFrameworkBugMessageAndExit();
109+
displayFrameworkBugMessageAndExit(
110+
activity.getString(R.string.zxing_msg_camera_framework_bug)
111+
);
107112
}
108113

109114
@Override
@@ -162,6 +167,13 @@ public void initializeFromIntent(Intent intent, Bundle savedInstanceState) {
162167
beepManager.setBeepEnabled(false);
163168
}
164169

170+
if (intent.hasExtra(Intents.Scan.SHOW_MISSING_CAMERA_PERMISSION_DIALOG)) {
171+
setShowMissingCameraPermissionDialog(
172+
intent.getBooleanExtra(Intents.Scan.SHOW_MISSING_CAMERA_PERMISSION_DIALOG, true),
173+
intent.getStringExtra(Intents.Scan.MISSING_CAMERA_PERMISSION_DIALOG_MESSAGE)
174+
);
175+
}
176+
165177
if (intent.hasExtra(Intents.Scan.TIMEOUT)) {
166178
handler.postDelayed(this::returnResultTimeout, intent.getLongExtra(Intents.Scan.TIMEOUT, 0L));
167179
}
@@ -234,9 +246,7 @@ private void openCameraWithPermission() {
234246
new String[]{Manifest.permission.CAMERA},
235247
cameraPermissionReqCode);
236248
askedPermission = true;
237-
} else {
238-
// Wait for permission result
239-
}
249+
} // else wait for permission result
240250
}
241251

242252
/**
@@ -253,8 +263,13 @@ public void onRequestPermissionsResult(int requestCode, String permissions[], in
253263
// permission was granted
254264
barcodeView.resume();
255265
} else {
256-
// TODO: display better error message.
257-
displayFrameworkBugMessageAndExit();
266+
setMissingCameraPermissionResult();
267+
268+
if (showDialogIfMissingCameraPermission) {
269+
displayFrameworkBugMessageAndExit(missingCameraPermissionDialogMessage);
270+
} else {
271+
closeAndFinish();
272+
}
258273
}
259274
}
260275
}
@@ -369,6 +384,12 @@ protected void closeAndFinish() {
369384
inactivityTimer.cancel();
370385
}
371386

387+
private void setMissingCameraPermissionResult() {
388+
Intent intent = new Intent(Intents.Scan.ACTION);
389+
intent.putExtra(Intents.Scan.MISSING_CAMERA_PERMISSION, true);
390+
activity.setResult(Activity.RESULT_CANCELED, intent);
391+
}
392+
372393
protected void returnResultTimeout() {
373394
Intent intent = new Intent(Intents.Scan.ACTION);
374395
intent.putExtra(Intents.Scan.TIMEOUT, true);
@@ -382,25 +403,20 @@ protected void returnResult(BarcodeResult rawResult) {
382403
closeAndFinish();
383404
}
384405

385-
protected void displayFrameworkBugMessageAndExit() {
406+
protected void displayFrameworkBugMessageAndExit(String message) {
386407
if (activity.isFinishing() || this.destroyed || finishWhenClosed) {
387408
return;
388409
}
410+
411+
if (message.isEmpty()) {
412+
message = activity.getString(R.string.zxing_msg_camera_framework_bug);
413+
}
414+
389415
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
390416
builder.setTitle(activity.getString(R.string.zxing_app_name));
391-
builder.setMessage(activity.getString(R.string.zxing_msg_camera_framework_bug));
392-
builder.setPositiveButton(R.string.zxing_button_ok, new DialogInterface.OnClickListener() {
393-
@Override
394-
public void onClick(DialogInterface dialog, int which) {
395-
finish();
396-
}
397-
});
398-
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
399-
@Override
400-
public void onCancel(DialogInterface dialog) {
401-
finish();
402-
}
403-
});
417+
builder.setMessage(message);
418+
builder.setPositiveButton(R.string.zxing_button_ok, (dialog, which) -> finish());
419+
builder.setOnCancelListener(dialog -> finish());
404420
builder.show();
405421
}
406422

@@ -411,4 +427,29 @@ public static int getCameraPermissionReqCode() {
411427
public static void setCameraPermissionReqCode(int cameraPermissionReqCode) {
412428
CaptureManager.cameraPermissionReqCode = cameraPermissionReqCode;
413429
}
430+
431+
/**
432+
* If set to true, shows the default error dialog if camera permission is missing.
433+
* <p>
434+
* If set to false, instead the capture manager just finishes.
435+
* <p>
436+
* In both cases, the activity result is set to {@link Intents.Scan#MISSING_CAMERA_PERMISSION}
437+
* and cancelled
438+
*/
439+
public void setShowMissingCameraPermissionDialog(boolean visible) {
440+
setShowMissingCameraPermissionDialog(visible, "");
441+
}
442+
443+
/**
444+
* If set to true, shows the specified error dialog message if camera permission is missing.
445+
* <p>
446+
* If set to false, instead the capture manager just finishes.
447+
* <p>
448+
* In both cases, the activity result is set to {@link Intents.Scan#MISSING_CAMERA_PERMISSION}
449+
* and cancelled
450+
*/
451+
public void setShowMissingCameraPermissionDialog(boolean visible, String message) {
452+
showDialogIfMissingCameraPermission = visible;
453+
missingCameraPermissionDialogMessage = message != null ? message : "";
454+
}
414455
}

0 commit comments

Comments
 (0)