From 49601e62e5f7e0233f2f89138f7c43ecd0e9fa09 Mon Sep 17 00:00:00 2001 From: srowen Date: Tue, 9 Feb 2010 09:14:16 +0000 Subject: [PATCH] Issue 112 git-svn-id: https://zxing.googlecode.com/svn/trunk@1204 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- android/build.xml | 2 + .../zxing/client/android/CaptureActivity.java | 70 ++++++++++++++++-- .../android/CaptureActivityHandler.java | 7 +- .../zxing/client/android/DecodeThread.java | 72 +++---------------- .../google/zxing/client/android/Intents.java | 15 +++- 5 files changed, 95 insertions(+), 71 deletions(-) diff --git a/android/build.xml b/android/build.xml index 6a03153f8..5892b8c64 100644 --- a/android/build.xml +++ b/android/build.xml @@ -202,6 +202,8 @@ limitations under the License. + + diff --git a/android/src/com/google/zxing/client/android/CaptureActivity.java b/android/src/com/google/zxing/client/android/CaptureActivity.java index 67b24bc0d..0dbf33663 100755 --- a/android/src/com/google/zxing/client/android/CaptureActivity.java +++ b/android/src/com/google/zxing/client/android/CaptureActivity.java @@ -16,6 +16,7 @@ package com.google.zxing.client.android; +import com.google.zxing.BarcodeFormat; import com.google.zxing.Result; import com.google.zxing.ResultPoint; import com.google.zxing.client.android.history.HistoryManager; @@ -65,6 +66,8 @@ import android.widget.ImageView; import android.widget.TextView; import java.io.IOException; +import java.util.Vector; +import java.util.regex.Pattern; /** * The barcode reader activity itself. This is loosely based on the CameraPreview @@ -73,7 +76,9 @@ import java.io.IOException; * @author dswitkin@google.com (Daniel Switkin) */ public final class CaptureActivity extends Activity implements SurfaceHolder.Callback { + private static final String TAG = "CaptureActivity"; + private static final Pattern COMMA_PATTERN = Pattern.compile(","); private static final int SHARE_ID = Menu.FIRST; private static final int HISTORY_ID = Menu.FIRST + 1; @@ -91,6 +96,30 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal private static final String PRODUCT_SEARCH_URL_SUFFIX = "/m/products/scan"; private static final String ZXING_URL = "http://zxing.appspot.com/scan"; + static final Vector PRODUCT_FORMATS; + static final Vector ONE_D_FORMATS; + static final Vector QR_CODE_FORMATS; + static final Vector ALL_FORMATS; + + static { + PRODUCT_FORMATS = new Vector(5); + PRODUCT_FORMATS.add(BarcodeFormat.UPC_A); + PRODUCT_FORMATS.add(BarcodeFormat.UPC_E); + PRODUCT_FORMATS.add(BarcodeFormat.EAN_13); + PRODUCT_FORMATS.add(BarcodeFormat.EAN_8); + PRODUCT_FORMATS.add(BarcodeFormat.RSS14); + ONE_D_FORMATS = new Vector(PRODUCT_FORMATS.size() + 3); + ONE_D_FORMATS.addAll(PRODUCT_FORMATS); + ONE_D_FORMATS.add(BarcodeFormat.CODE_39); + ONE_D_FORMATS.add(BarcodeFormat.CODE_128); + ONE_D_FORMATS.add(BarcodeFormat.ITF); + QR_CODE_FORMATS = new Vector(1); + QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE); + ALL_FORMATS = new Vector(ONE_D_FORMATS.size() + QR_CODE_FORMATS.size()); + ALL_FORMATS.addAll(ONE_D_FORMATS); + ALL_FORMATS.addAll(QR_CODE_FORMATS); + } + private enum Source { NATIVE_APP_INTENT, PRODUCT_SEARCH_LINK, @@ -111,7 +140,7 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal private boolean copyToClipboard; private Source source; private String sourceUrl; - private String decodeMode; + private Vector decodeFormats; private String versionName; private HistoryManager historyManager; @@ -177,31 +206,31 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal if (action.equals(Intents.Scan.ACTION)) { // Scan the formats the intent requested, and return the result to the calling activity. source = Source.NATIVE_APP_INTENT; - decodeMode = intent.getStringExtra(Intents.Scan.MODE); + decodeFormats = parseDecodeFormats(intent); resetStatusView(); } 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. source = Source.PRODUCT_SEARCH_LINK; sourceUrl = dataString; - decodeMode = Intents.Scan.PRODUCT_MODE; + decodeFormats = PRODUCT_FORMATS; resetStatusView(); } else if (dataString != null && dataString.equals(ZXING_URL)) { // Scan all formats and handle the results ourselves. // TODO: In the future we could allow the hyperlink to include a URL to send the results to. source = Source.ZXING_LINK; sourceUrl = dataString; - decodeMode = null; + decodeFormats = null; resetStatusView(); } else { // Scan all formats and handle the results ourselves (launched from Home). source = Source.NONE; - decodeMode = null; + decodeFormats = null; resetStatusView(); } } else { source = Source.NONE; - decodeMode = null; + decodeFormats = null; if (lastResult == null) { resetStatusView(); } @@ -214,6 +243,33 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal initBeepSound(); } + private static Vector parseDecodeFormats(Intent intent) { + String scanFormats = intent.getStringExtra(Intents.Scan.SCAN_FORMATS); + if (scanFormats != null) { + Vector formats = new Vector(); + try { + for (String format : COMMA_PATTERN.split(scanFormats)) { + formats.add(BarcodeFormat.valueOf(format)); + } + } catch (IllegalArgumentException iae) { + // ignore it then + } + } + String decodeMode = intent.getStringExtra(Intents.Scan.MODE); + if (decodeMode != null) { + if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) { + return PRODUCT_FORMATS; + } + if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) { + return QR_CODE_FORMATS; + } + if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) { + return ONE_D_FORMATS; + } + } + return null; + } + @Override protected void onPause() { super.onPause(); @@ -559,7 +615,7 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal } if (handler == null) { boolean beginScanning = lastResult == null; - handler = new CaptureActivityHandler(this, decodeMode, beginScanning); + handler = new CaptureActivityHandler(this, decodeFormats, beginScanning); } } diff --git a/android/src/com/google/zxing/client/android/CaptureActivityHandler.java b/android/src/com/google/zxing/client/android/CaptureActivityHandler.java index fd671603e..f3595ede7 100755 --- a/android/src/com/google/zxing/client/android/CaptureActivityHandler.java +++ b/android/src/com/google/zxing/client/android/CaptureActivityHandler.java @@ -16,6 +16,7 @@ package com.google.zxing.client.android; +import com.google.zxing.BarcodeFormat; import com.google.zxing.Result; import android.app.Activity; @@ -26,6 +27,8 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; +import java.util.Vector; + /** * This class handles all the messaging which comprises the state machine for capture. * @@ -43,10 +46,10 @@ public final class CaptureActivityHandler extends Handler { } CaptureActivityHandler(CaptureActivity activity, - String decodeMode, + Vector decodeFormats, boolean beginScanning) { this.activity = activity; - decodeThread = new DecodeThread(activity, decodeMode, + decodeThread = new DecodeThread(activity, decodeFormats, new ViewfinderResultPointCallback(activity.getViewfinderView())); decodeThread.start(); state = State.SUCCESS; diff --git a/android/src/com/google/zxing/client/android/DecodeThread.java b/android/src/com/google/zxing/client/android/DecodeThread.java index cd58239fb..a7242ec6d 100755 --- a/android/src/com/google/zxing/client/android/DecodeThread.java +++ b/android/src/com/google/zxing/client/android/DecodeThread.java @@ -51,33 +51,27 @@ final class DecodeThread extends Thread { private final MultiFormatReader multiFormatReader; private final ResultPointCallback resultPointCallback; - DecodeThread(CaptureActivity activity, String mode, ResultPointCallback resultPointCallback) { + DecodeThread(CaptureActivity activity, + Vector decodeFormats, + ResultPointCallback resultPointCallback) { this.activity = activity; multiFormatReader = new MultiFormatReader(); this.resultPointCallback = resultPointCallback; // The prefs can't change while the thread is running, so pick them up once here. - if (mode == null || mode.length() == 0) { + if (decodeFormats == null || decodeFormats.isEmpty()) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); boolean decode1D = prefs.getBoolean(PreferencesActivity.KEY_DECODE_1D, true); boolean decodeQR = prefs.getBoolean(PreferencesActivity.KEY_DECODE_QR, true); if (decode1D && decodeQR) { - setDecodeAllMode(); + doSetDecodeMode(CaptureActivity.ALL_FORMATS); } else if (decode1D) { - setDecode1DMode(); + doSetDecodeMode(CaptureActivity.ONE_D_FORMATS); } else if (decodeQR) { - setDecodeQRMode(); + doSetDecodeMode(CaptureActivity.QR_CODE_FORMATS); } } else { - if (mode.equals(Intents.Scan.PRODUCT_MODE)) { - setDecodeProductMode(); - } else if (mode.equals(Intents.Scan.ONE_D_MODE)) { - setDecode1DMode(); - } else if (mode.equals(Intents.Scan.QR_CODE_MODE)) { - setDecodeQRMode(); - } else { - setDecodeAllMode(); - } + doSetDecodeMode(decodeFormats); } } @@ -104,55 +98,11 @@ final class DecodeThread extends Thread { Looper.loop(); } - private void setDecodeProductMode() { - doSetDecodeMode(BarcodeFormat.UPC_A, - BarcodeFormat.UPC_E, - BarcodeFormat.EAN_13, - BarcodeFormat.EAN_8, - BarcodeFormat.RSS14); - } - - /** - * Select the 1D formats we want this client to decode by hand. - */ - private void setDecode1DMode() { - doSetDecodeMode(BarcodeFormat.UPC_A, - BarcodeFormat.UPC_E, - BarcodeFormat.EAN_13, - BarcodeFormat.EAN_8, - BarcodeFormat.CODE_39, - BarcodeFormat.CODE_128, - BarcodeFormat.ITF, - BarcodeFormat.RSS14); - } - - private void setDecodeQRMode() { - doSetDecodeMode(BarcodeFormat.QR_CODE); - } - - /** - * Instead of calling setHints(null), which would allow new formats to sneak in, we - * explicitly set which formats are available. - */ - private void setDecodeAllMode() { - doSetDecodeMode(BarcodeFormat.UPC_A, - BarcodeFormat.UPC_E, - BarcodeFormat.EAN_13, - BarcodeFormat.EAN_8, - BarcodeFormat.CODE_39, - BarcodeFormat.CODE_128, - BarcodeFormat.ITF, - BarcodeFormat.RSS14, - BarcodeFormat.QR_CODE); - } - - private void doSetDecodeMode(BarcodeFormat... formats) { + private void doSetDecodeMode(Vector vector) { Hashtable hints = new Hashtable(3); - Vector vector = new Vector(formats.length); - for (BarcodeFormat format : formats) { - vector.addElement(format); + if (vector != null) { + hints.put(DecodeHintType.POSSIBLE_FORMATS, vector); } - hints.put(DecodeHintType.POSSIBLE_FORMATS, vector); hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback); multiFormatReader.setHints(hints); } diff --git a/android/src/com/google/zxing/client/android/Intents.java b/android/src/com/google/zxing/client/android/Intents.java index 10e088ac1..39fc91592 100755 --- a/android/src/com/google/zxing/client/android/Intents.java +++ b/android/src/com/google/zxing/client/android/Intents.java @@ -36,10 +36,23 @@ 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 (optional). + * one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}). + * Optional. + * + * Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_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"; + /** * Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get * prices, reviews, etc. for products.