X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=android%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fclient%2Fandroid%2FCaptureActivity.java;h=8198642159a281ddfeebb0a6728c0f378e3a6f7b;hb=96160fca14b3591927d3fdb6bd8ce2fae5f170cb;hp=d95abb8aff0e378a774b42cf05b72e55e111fbdc;hpb=2dfb4f0f6c6fb9dca2baba426d7cacb21d283c4f;p=zxing.git diff --git a/android/src/com/google/zxing/client/android/CaptureActivity.java b/android/src/com/google/zxing/client/android/CaptureActivity.java index d95abb8a..81986421 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,27 +140,32 @@ 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 characterSet; private String versionName; private HistoryManager historyManager; - + private final OnCompletionListener beepListener = new BeepListener(); private final DialogInterface.OnClickListener aboutListener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialogInterface, int i) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.zxing_url))); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); startActivity(intent); } }; + ViewfinderView getViewfinderView() { + return viewfinderView; + } + public Handler getHandler() { return handler; } @Override public void onCreate(Bundle icicle) { - Log.i(TAG, "Creating CaptureActivity"); super.onCreate(icicle); Window window = getWindow(); @@ -174,31 +208,33 @@ 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(); } + characterSet = intent.getStringExtra(Intents.Scan.CHARACTER_SET); } else { source = Source.NONE; - decodeMode = null; + decodeFormats = null; + characterSet = null; if (lastResult == null) { resetStatusView(); } @@ -211,6 +247,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(); @@ -230,7 +293,9 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal return true; } else if ((source == Source.NONE || source == Source.ZXING_LINK) && lastResult != null) { resetStatusView(); - handler.sendEmptyMessage(R.id.restart_preview); + if (handler != null) { + handler.sendEmptyMessage(R.id.restart_preview); + } return true; } } else if (keyCode == KeyEvent.KEYCODE_FOCUS || keyCode == KeyEvent.KEYCODE_CAMERA) { @@ -243,8 +308,10 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); - menu.add(0, SHARE_ID, 0, R.string.menu_share).setIcon(R.drawable.share_menu_item); - menu.add(0, HISTORY_ID, 0, R.string.menu_history).setIcon(android.R.drawable.ic_menu_recent_history); + menu.add(0, SHARE_ID, 0, R.string.menu_share) + .setIcon(android.R.drawable.ic_menu_share); + menu.add(0, HISTORY_ID, 0, R.string.menu_history) + .setIcon(android.R.drawable.ic_menu_recent_history); menu.add(0, SETTINGS_ID, 0, R.string.menu_settings) .setIcon(android.R.drawable.ic_menu_preferences); menu.add(0, HELP_ID, 0, R.string.menu_help) @@ -267,6 +334,7 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal switch (item.getItemId()) { case SHARE_ID: { Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.setClassName(this, ShareActivity.class.getName()); startActivity(intent); break; @@ -278,12 +346,14 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal } case SETTINGS_ID: { Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.setClassName(this, PreferencesActivity.class.getName()); startActivity(intent); break; } case HELP_ID: { Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.setClassName(this, HelpActivity.class.getName()); startActivity(intent); break; @@ -458,6 +528,7 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal // Hand back whatever action they requested - this can be changed to Intents.Scan.ACTION when // the deprecated intent is retired. Intent intent = new Intent(getIntent().getAction()); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.putExtra(Intents.Scan.RESULT, rawResult.toString()); intent.putExtra(Intents.Scan.RESULT_FORMAT, rawResult.getBarcodeFormat().toString()); Message message = Message.obtain(handler, R.id.return_scan_result); @@ -479,7 +550,7 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal * run. The easiest way to do this is to check android:versionCode from the manifest, and compare * it to a value stored as a preference. */ - private void showHelpOnFirstLaunch() { + private boolean showHelpOnFirstLaunch() { try { PackageInfo info = getPackageManager().getPackageInfo(PACKAGE_NAME, 0); int currentVersion = info.versionCode; @@ -491,12 +562,15 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal if (currentVersion > lastVersion) { prefs.edit().putInt(PreferencesActivity.KEY_HELP_VERSION_SHOWN, currentVersion).commit(); Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.setClassName(this, HelpActivity.class.getName()); startActivity(intent); + return true; } } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, e); } + return false; } /** @@ -505,8 +579,11 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal */ private void initBeepSound() { if (playBeep && mediaPlayer == null) { + // The volume on STREAM_SYSTEM is not adjustable, and users found it too loud, + // so we now play on the music stream. + setVolumeControlStream(AudioManager.STREAM_MUSIC); mediaPlayer = new MediaPlayer(); - mediaPlayer.setAudioStreamType(AudioManager.STREAM_SYSTEM); + mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setOnCompletionListener(beepListener); AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.beep); @@ -537,14 +614,33 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal CameraManager.get().openDriver(surfaceHolder); } catch (IOException ioe) { Log.w(TAG, ioe); + displayFrameworkBugMessageAndExit(); + return; + } catch (RuntimeException e) { + // Barcode Scanner has seen crashes in the wild of this variety: + // java.?lang.?RuntimeException: Fail to connect to camera service + Log.e(TAG, e.toString()); + displayFrameworkBugMessageAndExit(); return; } if (handler == null) { boolean beginScanning = lastResult == null; - handler = new CaptureActivityHandler(this, decodeMode, beginScanning); + handler = new CaptureActivityHandler(this, decodeFormats, characterSet, beginScanning); } } + private void displayFrameworkBugMessageAndExit() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(getString(R.string.app_name)); + builder.setMessage(getString(R.string.msg_camera_framework_bug)); + builder.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialogInterface, int i) { + finish(); + } + }); + builder.show(); + } + private void resetStatusView() { resultView.setVisibility(View.GONE); statusView.setVisibility(View.VISIBLE);