From e3e0a12da8ec06d46c50f247151a0eb58761faa6 Mon Sep 17 00:00:00 2001 From: "dswitkin@google.com" Date: Tue, 17 May 2011 19:20:38 +0000 Subject: [PATCH] Issue 835: Added support for specifying a width and height for the scanning rectangle when launching Barcode Scanner by Intent. git-svn-id: https://zxing.googlecode.com/svn/trunk@1776 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- .../zxing/client/android/CaptureActivity.java | 7 ++ .../client/android/DecodeFormatManager.java | 4 +- .../zxing/client/android/DecodeHandler.java | 2 - .../google/zxing/client/android/Intents.java | 88 ++++++++++--------- .../client/android/camera/CameraManager.java | 31 ++++++- .../client/androidtest/ZXingTestActivity.java | 62 ++++++------- 6 files changed, 118 insertions(+), 76 deletions(-) diff --git a/android/src/com/google/zxing/client/android/CaptureActivity.java b/android/src/com/google/zxing/client/android/CaptureActivity.java index e15012ef5..4cbaf7c73 100755 --- a/android/src/com/google/zxing/client/android/CaptureActivity.java +++ b/android/src/com/google/zxing/client/android/CaptureActivity.java @@ -194,6 +194,13 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal // Scan the formats the intent requested, and return the result to the calling activity. source = Source.NATIVE_APP_INTENT; decodeFormats = DecodeFormatManager.parseDecodeFormats(intent); + if (intent.hasExtra(Intents.Scan.WIDTH) && intent.hasExtra(Intents.Scan.HEIGHT)) { + int width = intent.getIntExtra(Intents.Scan.WIDTH, 0); + int height = intent.getIntExtra(Intents.Scan.HEIGHT, 0); + if (width > 0 && height > 0) { + CameraManager.get().setManualFramingRect(width, height); + } + } } else if (dataString != null && dataString.contains(PRODUCT_SEARCH_URL_PREFIX) && dataString.contains(PRODUCT_SEARCH_URL_SUFFIX)) { // Scan only products and send the result to mobile Product Search. diff --git a/android/src/com/google/zxing/client/android/DecodeFormatManager.java b/android/src/com/google/zxing/client/android/DecodeFormatManager.java index 799d15b18..e4fd90a11 100644 --- a/android/src/com/google/zxing/client/android/DecodeFormatManager.java +++ b/android/src/com/google/zxing/client/android/DecodeFormatManager.java @@ -56,7 +56,7 @@ final class DecodeFormatManager { static Vector parseDecodeFormats(Intent intent) { List scanFormats = null; - String scanFormatsString = intent.getStringExtra(Intents.Scan.SCAN_FORMATS); + String scanFormatsString = intent.getStringExtra(Intents.Scan.FORMATS); if (scanFormatsString != null) { scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString)); } @@ -64,7 +64,7 @@ final class DecodeFormatManager { } static Vector parseDecodeFormats(Uri inputUri) { - List formats = inputUri.getQueryParameters(Intents.Scan.SCAN_FORMATS); + List formats = inputUri.getQueryParameters(Intents.Scan.FORMATS); if (formats != null && formats.size() == 1 && formats.get(0) != null){ formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0))); } diff --git a/android/src/com/google/zxing/client/android/DecodeHandler.java b/android/src/com/google/zxing/client/android/DecodeHandler.java index c7f8e7265..0687554e2 100644 --- a/android/src/com/google/zxing/client/android/DecodeHandler.java +++ b/android/src/com/google/zxing/client/android/DecodeHandler.java @@ -49,7 +49,6 @@ final class DecodeHandler extends Handler { public void handleMessage(Message message) { switch (message.what) { case R.id.decode: - //Log.d(TAG, "Got decode message"); decode((byte[]) message.obj, message.arg1, message.arg2); break; case R.id.quit: @@ -86,7 +85,6 @@ final class DecodeHandler extends Handler { Bundle bundle = new Bundle(); bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap()); message.setData(bundle); - //Log.d(TAG, "Sending decode succeeded message..."); message.sendToTarget(); } else { Message message = Message.obtain(activity.getHandler(), R.id.decode_failed); diff --git a/android/src/com/google/zxing/client/android/Intents.java b/android/src/com/google/zxing/client/android/Intents.java index 7f72ddf49..624ad7dc2 100755 --- a/android/src/com/google/zxing/client/android/Intents.java +++ b/android/src/com/google/zxing/client/android/Intents.java @@ -36,28 +36,13 @@ public final class Intents { /** * By default, sending Scan.ACTION will decode all barcodes that we understand. However it * may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with - * one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}). - * Optional. + * one of the values below. * - * Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_FORMATS}. + * Setting this is effectively shorthand for setting explicit formats with {@link #FORMATS}. * It is overridden by that setting. */ public static final String MODE = "SCAN_MODE"; - /** - * Comma-separated list of formats to scan for. The values must match the names of - * {@link com.google.zxing.BarcodeFormat}s, such as {@link com.google.zxing.BarcodeFormat#EAN_13}. - * Example: "EAN_13,EAN_8,QR_CODE" - * - * This overrides {@link #MODE}. - */ - public static final String SCAN_FORMATS = "SCAN_FORMATS"; - - /** - * @see com.google.zxing.DecodeHintType#CHARACTER_SET - */ - public static final String CHARACTER_SET = "CHARACTER_SET"; - /** * Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get * prices, reviews, etc. for products. @@ -65,7 +50,7 @@ public final class Intents { public static final String PRODUCT_MODE = "PRODUCT_MODE"; /** - * Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128). + * Decode only 1D barcodes. */ public static final String ONE_D_MODE = "ONE_D_MODE"; @@ -79,6 +64,28 @@ public final class Intents { */ public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE"; + /** + * Comma-separated list of formats to scan for. The values must match the names of + * {@link com.google.zxing.BarcodeFormat}s, e.g. {@link com.google.zxing.BarcodeFormat#EAN_13}. + * Example: "EAN_13,EAN_8,QR_CODE" + * + * This overrides {@link #MODE}. + */ + public static final String FORMATS = "SCAN_FORMATS"; + + /** + * @see com.google.zxing.DecodeHintType#CHARACTER_SET + */ + public static final String CHARACTER_SET = "CHARACTER_SET"; + + /** + * Optional parameters to specify the width and height of the scanning rectangle in pixels. + * The app will try to honor these, but will clamp them to the size of the preview frame. + * You should specify both or neither, and pass the size as an int. + */ + public static final String WIDTH = "SCAN_WIDTH"; + public static final String HEIGHT = "SCAN_HEIGHT"; + /** * If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which * requested the scan via startSubActivity(). The barcodes contents can be retrieved with @@ -127,11 +134,11 @@ public final class Intents { * Intent.putExtra(TYPE, type) with one of Contents.Type. */ public static final String TYPE = "ENCODE_TYPE"; - + /** - * The barcode format to be displayed. If this isn't specified or is blank, + * The barcode format to be displayed. If this isn't specified or is blank, * it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where - * format is one of Contents.Format. + * format is one of Contents.Format. */ public static final String FORMAT = "ENCODE_FORMAT"; @@ -160,30 +167,29 @@ public final class Intents { } public static final class WifiConnect { - /** - * Internal intent used to trigger connection to a wi-fi network. - */ - public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT"; + /** + * Internal intent used to trigger connection to a wi-fi network. + */ + public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT"; - /** - * The network to connect to, all the configuration provided here. - */ - public static final String SSID = "SSID"; + /** + * The network to connect to, all the configuration provided here. + */ + public static final String SSID = "SSID"; - /** - * The network to connect to, all the configuration provided here. - */ - public static final String TYPE = "TYPE"; + /** + * The network to connect to, all the configuration provided here. + */ + public static final String TYPE = "TYPE"; - /** - * The network to connect to, all the configuration provided here. - */ - public static final String PASSWORD = "PASSWORD"; - - private WifiConnect() { - } - } + /** + * The network to connect to, all the configuration provided here. + */ + public static final String PASSWORD = "PASSWORD"; + private WifiConnect() { + } + } public static final class Share { /** diff --git a/android/src/com/google/zxing/client/android/camera/CameraManager.java b/android/src/com/google/zxing/client/android/camera/CameraManager.java index b1f4e681a..3a28864fd 100755 --- a/android/src/com/google/zxing/client/android/camera/CameraManager.java +++ b/android/src/com/google/zxing/client/android/camera/CameraManager.java @@ -148,6 +148,11 @@ public final class CameraManager { FlashlightManager.disableFlashlight(); camera.release(); camera = null; + + // Make sure to clear these each time we close the camera, so that any scanning rect + // requested by intent is forgotten. + framingRect = null; + framingRectInPreview = null; } } @@ -217,11 +222,11 @@ public final class CameraManager { * @return The rectangle to draw on screen in window coordinates. */ public Rect getFramingRect() { - Point screenResolution = configManager.getScreenResolution(); if (framingRect == null) { if (camera == null) { return null; } + Point screenResolution = configManager.getScreenResolution(); int width = screenResolution.x * 3 / 4; if (width < MIN_FRAME_WIDTH) { width = MIN_FRAME_WIDTH; @@ -260,6 +265,28 @@ public final class CameraManager { return framingRectInPreview; } + /** + * Allows third party apps to specify the scanning rectangle dimensions, rather than determine + * them automatically based on screen resolution. + * + * @param width The width in pixels to scan. + * @param height The height in pixels to scan. + */ + public void setManualFramingRect(int width, int height) { + Point screenResolution = configManager.getScreenResolution(); + if (width > screenResolution.x) { + width = screenResolution.x; + } + if (height > screenResolution.y) { + height = screenResolution.y; + } + int leftOffset = (screenResolution.x - width) / 2; + int topOffset = (screenResolution.y - height) / 2; + framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height); + Log.d(TAG, "Calculated manual framing rect: " + framingRect); + framingRectInPreview = null; + } + /** * A factory method to build the appropriate LuminanceSource object based on the format * of the preview buffers, as described by Camera.Parameters. @@ -273,6 +300,8 @@ public final class CameraManager { Rect rect = getFramingRectInPreview(); int previewFormat = configManager.getPreviewFormat(); String previewFormatString = configManager.getPreviewFormatString(); + + // FIXME(dswitkin): Don't access the preferences on every scan, this is expensive! SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); boolean reverseImage = sharedPrefs.getBoolean(PreferencesActivity.KEY_REVERSE_IMAGE, false); diff --git a/androidtest/src/com/google/zxing/client/androidtest/ZXingTestActivity.java b/androidtest/src/com/google/zxing/client/androidtest/ZXingTestActivity.java index d8f76c209..99d5069e7 100755 --- a/androidtest/src/com/google/zxing/client/androidtest/ZXingTestActivity.java +++ b/androidtest/src/com/google/zxing/client/androidtest/ZXingTestActivity.java @@ -38,21 +38,21 @@ public final class ZXingTestActivity extends Activity { super.onCreate(icicle); setContentView(R.layout.test); - findViewById(R.id.take_test_photos).setOnClickListener(mTakeTestPhotos); - findViewById(R.id.get_camera_parameters).setOnClickListener(mGetCameraParameters); - findViewById(R.id.run_benchmark).setOnClickListener(mRunBenchmark); - findViewById(R.id.scan_product).setOnClickListener(mScanProduct); - findViewById(R.id.scan_qr_code).setOnClickListener(mScanQRCode); - findViewById(R.id.scan_anything).setOnClickListener(mScanAnything); - findViewById(R.id.search_book_contents).setOnClickListener(mSearchBookContents); - findViewById(R.id.encode_url).setOnClickListener(mEncodeURL); - findViewById(R.id.encode_email).setOnClickListener(mEncodeEmail); - findViewById(R.id.encode_phone).setOnClickListener(mEncodePhone); - findViewById(R.id.encode_sms).setOnClickListener(mEncodeSMS); - findViewById(R.id.encode_contact).setOnClickListener(mEncodeContact); - findViewById(R.id.encode_location).setOnClickListener(mEncodeLocation); - findViewById(R.id.encode_bad_data).setOnClickListener(mEncodeBadData); - findViewById(R.id.share_via_barcode).setOnClickListener(mShareViaBarcode); + findViewById(R.id.take_test_photos).setOnClickListener(takeTestPhotos); + findViewById(R.id.get_camera_parameters).setOnClickListener(getCameraParameters); + findViewById(R.id.run_benchmark).setOnClickListener(runBenchmark); + findViewById(R.id.scan_product).setOnClickListener(scanProduct); + findViewById(R.id.scan_qr_code).setOnClickListener(scanQRCode); + findViewById(R.id.scan_anything).setOnClickListener(scanAnything); + findViewById(R.id.search_book_contents).setOnClickListener(searchBookContents); + findViewById(R.id.encode_url).setOnClickListener(encodeURL); + findViewById(R.id.encode_email).setOnClickListener(encodeEmail); + findViewById(R.id.encode_phone).setOnClickListener(encodePhone); + findViewById(R.id.encode_sms).setOnClickListener(encodeSMS); + findViewById(R.id.encode_contact).setOnClickListener(encodeContact); + findViewById(R.id.encode_location).setOnClickListener(encodeLocation); + findViewById(R.id.encode_bad_data).setOnClickListener(encodeBadData); + findViewById(R.id.share_via_barcode).setOnClickListener(shareViaBarcode); } @Override @@ -86,7 +86,7 @@ public final class ZXingTestActivity extends Activity { return super.onOptionsItemSelected(item); } - public final Button.OnClickListener mTakeTestPhotos = new Button.OnClickListener() { + public final Button.OnClickListener takeTestPhotos = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setClassName(ZXingTestActivity.this, CameraTestActivity.class.getName()); @@ -95,7 +95,7 @@ public final class ZXingTestActivity extends Activity { } }; - public final Button.OnClickListener mGetCameraParameters = new Button.OnClickListener() { + public final Button.OnClickListener getCameraParameters = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setClassName(ZXingTestActivity.this, CameraTestActivity.class.getName()); @@ -104,7 +104,7 @@ public final class ZXingTestActivity extends Activity { } }; - public final Button.OnClickListener mRunBenchmark = new Button.OnClickListener() { + public final Button.OnClickListener runBenchmark = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setClassName(ZXingTestActivity.this, BenchmarkActivity.class.getName()); @@ -112,15 +112,17 @@ public final class ZXingTestActivity extends Activity { } }; - public final Button.OnClickListener mScanProduct = new Button.OnClickListener() { + public final Button.OnClickListener scanProduct = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent("com.google.zxing.client.android.SCAN"); intent.putExtra("SCAN_MODE", "PRODUCT_MODE"); + intent.putExtra("SCAN_WIDTH", 800); + intent.putExtra("SCAN_HEIGHT", 200); startActivityForResult(intent, 0); } }; - public final Button.OnClickListener mScanQRCode = new Button.OnClickListener() { + public final Button.OnClickListener scanQRCode = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent("com.google.zxing.client.android.SCAN"); intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); @@ -128,14 +130,14 @@ public final class ZXingTestActivity extends Activity { } }; - public final Button.OnClickListener mScanAnything = new Button.OnClickListener() { + public final Button.OnClickListener scanAnything = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent("com.google.zxing.client.android.SCAN"); startActivityForResult(intent, 0); } }; - public final Button.OnClickListener mSearchBookContents = new Button.OnClickListener() { + public final Button.OnClickListener searchBookContents = new Button.OnClickListener() { public void onClick(View v) { Intent intent = new Intent("com.google.zxing.client.android.SEARCH_BOOK_CONTENTS"); intent.putExtra("ISBN", "9780441014989"); @@ -157,31 +159,31 @@ public final class ZXingTestActivity extends Activity { } } - public final Button.OnClickListener mEncodeURL = new Button.OnClickListener() { + public final Button.OnClickListener encodeURL = new Button.OnClickListener() { public void onClick(View v) { encodeBarcode("TEXT_TYPE", "http://www.nytimes.com"); } }; - public final Button.OnClickListener mEncodeEmail = new Button.OnClickListener() { + public final Button.OnClickListener encodeEmail = new Button.OnClickListener() { public void onClick(View v) { encodeBarcode("EMAIL_TYPE", "foo@example.com"); } }; - public final Button.OnClickListener mEncodePhone = new Button.OnClickListener() { + public final Button.OnClickListener encodePhone = new Button.OnClickListener() { public void onClick(View v) { encodeBarcode("PHONE_TYPE", "2125551212"); } }; - public final Button.OnClickListener mEncodeSMS = new Button.OnClickListener() { + public final Button.OnClickListener encodeSMS = new Button.OnClickListener() { public void onClick(View v) { encodeBarcode("SMS_TYPE", "2125551212"); } }; - public final Button.OnClickListener mEncodeContact = new Button.OnClickListener() { + public final Button.OnClickListener encodeContact = new Button.OnClickListener() { public void onClick(View v) { Bundle bundle = new Bundle(); bundle.putString(Contacts.Intents.Insert.NAME, "Jenny"); @@ -192,7 +194,7 @@ public final class ZXingTestActivity extends Activity { } }; - public final Button.OnClickListener mEncodeLocation = new Button.OnClickListener() { + public final Button.OnClickListener encodeLocation = new Button.OnClickListener() { public void onClick(View v) { Bundle bundle = new Bundle(); bundle.putFloat("LAT", 40.829208f); @@ -201,13 +203,13 @@ public final class ZXingTestActivity extends Activity { } }; - public final Button.OnClickListener mEncodeBadData = new Button.OnClickListener() { + public final Button.OnClickListener encodeBadData = new Button.OnClickListener() { public void onClick(View v) { encodeBarcode(null, "bar"); } }; - public final Button.OnClickListener mShareViaBarcode = new Button.OnClickListener() { + public final Button.OnClickListener shareViaBarcode = new Button.OnClickListener() { public void onClick(View v) { startActivity(new Intent("com.google.zxing.client.android.SHARE")); }