Merge pull request #135 from slepmog/master

Adding ability to select camera when integrating via intent
This commit is contained in:
Sean Owen 2014-05-01 16:30:44 +01:00
commit 20d423c317
5 changed files with 116 additions and 26 deletions

View file

@ -249,25 +249,50 @@ public class IntentIntegrator {
}
/**
* Initiates a scan for all known barcode types.
* Initiates a scan for all known barcode types with the default camera.
*
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwiseo
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan() {
return initiateScan(ALL_CODE_TYPES);
return initiateScan(ALL_CODE_TYPES, -1);
}
/**
* Initiates a scan for all known barcode types with the specified camera.
*
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan(int cameraId) {
return initiateScan(ALL_CODE_TYPES, cameraId);
}
/**
* Initiates a scan only for a certain set of barcode types, given as strings corresponding
* Initiates a scan, using the default camera, only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
return initiateScan(desiredBarcodeFormats, -1);
}
/**
* Initiates a scan, using the specified camera, only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats, int cameraId) {
Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
@ -283,6 +308,11 @@ public class IntentIntegrator {
}
intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString());
}
// check requested camera ID
if (cameraId >= 0) {
intentScan.putExtra("SCAN_CAMERA_ID", cameraId);
}
String targetAppPackage = findTargetAppPackage(intentScan);
if (targetAppPackage == null) {

View file

@ -218,6 +218,13 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
cameraManager.setManualFramingRect(width, height);
}
}
if (intent.hasExtra(Intents.Scan.CAMERA_ID)) {
int cameraId = intent.getIntExtra(Intents.Scan.CAMERA_ID, -1);
if (cameraId >= 0) {
cameraManager.setManualCameraId(cameraId);
}
}
String customPromptMessage = intent.getStringExtra(Intents.Scan.PROMPT_MESSAGE);
if (customPromptMessage != null) {

View file

@ -80,6 +80,13 @@ public final class Intents {
* Example: "EAN_13,EAN_8,QR_CODE". This overrides {@link #MODE}.
*/
public static final String FORMATS = "SCAN_FORMATS";
/**
* Optional parameter to specify the id of the camera from which to recognize barcodes.
* Overrides the default camera that would otherwise would have been selected.
* If provided, should be an int.
*/
public static final String CAMERA_ID = "SCAN_CAMERA_ID";
/**
* @see com.google.zxing.DecodeHintType#CHARACTER_SET

View file

@ -52,6 +52,7 @@ public final class CameraManager {
private Rect framingRectInPreview;
private boolean initialized;
private boolean previewing;
private int requestedCameraId = -1;
private int requestedFramingRectWidth;
private int requestedFramingRectHeight;
/**
@ -65,7 +66,7 @@ public final class CameraManager {
this.configManager = new CameraConfigurationManager(context);
previewCallback = new PreviewCallback(configManager);
}
/**
* Opens the camera driver and initializes the hardware parameters.
*
@ -75,7 +76,13 @@ public final class CameraManager {
public synchronized void openDriver(SurfaceHolder holder) throws IOException {
Camera theCamera = camera;
if (theCamera == null) {
theCamera = OpenCameraInterface.open();
if (requestedCameraId >= 0) {
theCamera = OpenCameraInterface.open(requestedCameraId);
} else {
theCamera = OpenCameraInterface.open();
}
if (theCamera == null) {
throw new IOException();
}
@ -265,6 +272,21 @@ public final class CameraManager {
return framingRectInPreview;
}
/**
* Allows third party apps to specify the camera ID, rather than determine
* it automatically based on available cameras and their orientation.
*
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
*/
public synchronized void setManualCameraId(int cameraId) {
if (initialized) {
throw new IllegalStateException();
} else {
requestedCameraId = cameraId;
}
}
/**
* Allows third party apps to specify the scanning rectangle dimensions, rather than determine
* them automatically based on screen resolution.

View file

@ -26,39 +26,63 @@ public final class OpenCameraInterface {
private OpenCameraInterface() {
}
/**
* Opens a rear-facing camera with {@link Camera#open(int)}, if one exists, or opens camera 0.
* Opens the requested camera with {@link Camera#open(int)}, if one exists.
*
* @param cameraId camera ID of the camera to use. A negative value means "no preference"
* @return handle to {@link Camera} that was opened
*/
public static Camera open() {
public static Camera open(int cameraId) {
int numCameras = Camera.getNumberOfCameras();
if (numCameras == 0) {
Log.w(TAG, "No cameras!");
return null;
}
int index = 0;
while (index < numCameras) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(index, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
break;
boolean explicitRequest = cameraId >= 0;
if (!explicitRequest) {
// Select a camera if no explicit camera requested
int index = 0;
while (index < numCameras) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(index, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
break;
}
index++;
}
cameraId = index;
}
Camera camera;
if (cameraId < numCameras) {
Log.i(TAG, "Opening camera #" + cameraId);
camera = Camera.open(cameraId);
} else {
if (explicitRequest) {
Log.w(TAG, "Requested camera does not exist: " + cameraId);
camera = null;
} else {
Log.i(TAG, "No camera facing back; returning camera #0");
camera = Camera.open(0);
}
index++;
}
Camera camera;
if (index < numCameras) {
Log.i(TAG, "Opening camera #" + index);
camera = Camera.open(index);
} else {
Log.i(TAG, "No camera facing back; returning camera #0");
camera = Camera.open(0);
}
return camera;
}
/**
* Opens a rear-facing camera with {@link Camera#open(int)}, if one exists, or opens camera 0.
*
* @return handle to {@link Camera} that was opened
*/
public static Camera open() {
return open(-1);
}
}