From baaa39f223d7328f96cfd42d3b3ea5fdd253a7a1 Mon Sep 17 00:00:00 2001 From: dswitkin Date: Mon, 10 Nov 2008 20:50:34 +0000 Subject: [PATCH 1/1] Did a bunch of renaming, there was no need for the Barcodes prefix. git-svn-id: http://zxing.googlecode.com/svn/trunk@682 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- android/AndroidManifest.xml | 6 +- .../zxing/client/android/CaptureActivity.java | 420 ++++++++++++++++++ .../android/CaptureActivityHandler.java | 111 +++++ .../zxing/client/android/DecodeThread.java | 8 +- .../zxing/client/android/EncodeActivity.java | 139 ++++++ .../client/android/PreferencesActivity.java | 59 +++ 6 files changed, 736 insertions(+), 7 deletions(-) create mode 100755 android/src/com/google/zxing/client/android/CaptureActivity.java create mode 100755 android/src/com/google/zxing/client/android/CaptureActivityHandler.java create mode 100755 android/src/com/google/zxing/client/android/EncodeActivity.java create mode 100755 android/src/com/google/zxing/client/android/PreferencesActivity.java diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index dad8fabb..59c30adc 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -24,7 +24,7 @@ versionName is 2.31, 2.4, or 3.0. --> android:versionCode="6"> - @@ -42,10 +42,10 @@ versionName is 2.31, 2.4, or 3.0. --> - - + diff --git a/android/src/com/google/zxing/client/android/CaptureActivity.java b/android/src/com/google/zxing/client/android/CaptureActivity.java new file mode 100755 index 00000000..53904b67 --- /dev/null +++ b/android/src/com/google/zxing/client/android/CaptureActivity.java @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.android; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.AssetFileDescriptor; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.media.MediaPlayer.OnCompletionListener; +import android.net.Uri; +import android.os.Bundle; +import android.os.Message; +import android.preference.PreferenceManager; +import android.text.SpannableStringBuilder; +import android.text.style.UnderlineSpan; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; +import com.google.zxing.Result; +import com.google.zxing.ResultPoint; +import com.google.zxing.client.android.result.ResultButtonListener; +import com.google.zxing.client.android.result.ResultHandler; +import com.google.zxing.client.android.result.ResultHandlerFactory; + +import java.io.IOException; + +/** + * The barcode reader activity itself. This is loosely based on the CameraPreview + * example included in the Android SDK. + */ +public final class CaptureActivity extends Activity implements SurfaceHolder.Callback { + + private static final int SHARE_ID = Menu.FIRST; + private static final int SETTINGS_ID = Menu.FIRST + 1; + private static final int HELP_ID = Menu.FIRST + 2; + private static final int ABOUT_ID = Menu.FIRST + 3; + + private static final int MAX_RESULT_IMAGE_SIZE = 150; + private static final int INTENT_RESULT_DURATION = 1500; + private static final float BEEP_VOLUME = 0.15f; + + public CaptureActivityHandler mHandler; + + private ViewfinderView mViewfinderView; + private View mStatusView; + private View mResultView; + private MediaPlayer mMediaPlayer; + private Result mLastResult; + private boolean mHasSurface; + private boolean mPlayBeep; + private boolean mScanIntent; + private String mDecodeMode; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + Window window = getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + setContentView(R.layout.capture); + + CameraManager.init(getApplication()); + mViewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view); + mResultView = findViewById(R.id.result_view); + mStatusView = findViewById(R.id.status_view); + mHandler = null; + mLastResult = null; + mHasSurface = false; + } + + @Override + protected void onResume() { + super.onResume(); + + SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view); + SurfaceHolder surfaceHolder = surfaceView.getHolder(); + if (mHasSurface) { + // The activity was paused but not stopped, so the surface still exists. Therefore + // surfaceCreated() won't be called, so init the camera here. + initCamera(surfaceHolder); + } else { + // Install the callback and wait for surfaceCreated() to init the camera. + surfaceHolder.addCallback(this); + surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + } + + Intent intent = getIntent(); + if (intent != null && (intent.getAction().equals(Intents.Scan.ACTION) || + intent.getAction().equals(Intents.Scan.DEPRECATED_ACTION))) { + mScanIntent = true; + mDecodeMode = intent.getStringExtra(Intents.Scan.MODE); + resetStatusView(); + } else { + mScanIntent = false; + mDecodeMode = null; + if (mLastResult == null) { + resetStatusView(); + } + } + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + mPlayBeep = prefs.getBoolean(PreferencesActivity.KEY_PLAY_BEEP, true); + initBeepSound(); + } + + @Override + protected void onPause() { + super.onPause(); + if (mHandler != null) { + mHandler.quitSynchronously(); + mHandler = null; + } + CameraManager.get().closeDriver(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (mScanIntent) { + setResult(RESULT_CANCELED); + finish(); + return true; + } else if (mLastResult != null) { + resetStatusView(); + mHandler.sendEmptyMessage(R.id.restart_preview); + return true; + } + } else if (keyCode == KeyEvent.KEYCODE_FOCUS || keyCode == KeyEvent.KEYCODE_CAMERA) { + // Handle these events so they don't launch the Camera app + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + menu.add(0, SHARE_ID, 0, R.string.menu_share).setIcon(R.drawable.share_barcode); + 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) + .setIcon(android.R.drawable.ic_menu_help); + menu.add(0, ABOUT_ID, 0, R.string.menu_about) + .setIcon(android.R.drawable.ic_menu_info_details); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case SHARE_ID: { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setClassName(this, ShareActivity.class.getName()); + startActivity(intent); + break; + } + case SETTINGS_ID: { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setClassName(this, PreferencesActivity.class.getName()); + startActivity(intent); + break; + } + case HELP_ID: { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.title_help); + builder.setMessage(R.string.msg_help); + builder.setPositiveButton(R.string.button_ok, null); + builder.show(); + break; + } + case ABOUT_ID: { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.title_about); + builder.setMessage(getString(R.string.msg_about) + "\n\n" + getString(R.string.zxing_url)); + builder.setIcon(R.drawable.zxing_icon); + builder.setPositiveButton(R.string.button_open_browser, mAboutListener); + builder.setNegativeButton(R.string.button_cancel, null); + builder.show(); + break; + } + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onConfigurationChanged(Configuration config) { + // Do nothing, this is to prevent the activity from being restarted when the keyboard opens. + super.onConfigurationChanged(config); + } + + private final DialogInterface.OnClickListener mAboutListener = new DialogInterface.OnClickListener() { + public void onClick(android.content.DialogInterface dialogInterface, int i) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.zxing_url))); + startActivity(intent); + } + }; + + public void surfaceCreated(SurfaceHolder holder) { + if (!mHasSurface) { + mHasSurface = true; + initCamera(holder); + } + } + + public void surfaceDestroyed(SurfaceHolder holder) { + mHasSurface = false; + } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + + } + + /** + * A valid barcode has been found, so give an indication of success and show the results. + * + * @param rawResult The contents of the barcode. + * @param barcode A greyscale bitmap of the camera data which was decoded. + * @param duration How long the decoding took in milliseconds. + */ + public void handleDecode(Result rawResult, Bitmap barcode, int duration) { + mLastResult = rawResult; + playBeepSound(); + drawResultPoints(barcode, rawResult); + + if (mScanIntent) { + handleDecodeForScanIntent(rawResult, barcode, duration); + } else { + mStatusView.setVisibility(View.GONE); + mViewfinderView.setVisibility(View.GONE); + mResultView.setVisibility(View.VISIBLE); + + ImageView barcodeImageView = (ImageView) findViewById(R.id.barcode_image_view); + barcodeImageView.setMaxWidth(MAX_RESULT_IMAGE_SIZE); + barcodeImageView.setMaxHeight(MAX_RESULT_IMAGE_SIZE); + barcodeImageView.setImageBitmap(barcode); + + TextView formatTextView = (TextView) findViewById(R.id.format_text_view); + formatTextView.setText(getString(R.string.msg_default_format) + ": " + + rawResult.getBarcodeFormat().toString()); + + ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult); + TextView typeTextView = (TextView) findViewById(R.id.type_text_view); + typeTextView.setText(getString(R.string.msg_default_type) + ": " + + resultHandler.getType().toString()); + + TextView contentsTextView = (TextView) findViewById(R.id.contents_text_view); + CharSequence title = getString(resultHandler.getDisplayTitle()); + SpannableStringBuilder styled = new SpannableStringBuilder(title + "\n\n"); + styled.setSpan(new UnderlineSpan(), 0, title.length(), 0); + styled.append(resultHandler.getDisplayContents()); + contentsTextView.setText(styled); + + int buttonCount = resultHandler.getButtonCount(); + ViewGroup buttonView = (ViewGroup) findViewById(R.id.result_button_view); + buttonView.requestFocus(); + for (int x = 0; x < ResultHandler.MAX_BUTTON_COUNT; x++) { + Button button = (Button) buttonView.getChildAt(x); + if (x < buttonCount) { + button.setVisibility(View.VISIBLE); + button.setText(resultHandler.getButtonText(x)); + button.setOnClickListener(new ResultButtonListener(resultHandler, x)); + } else { + button.setVisibility(View.GONE); + } + } + } + } + + /** + * Superimpose a line for 1D or dots for 2D to highlight the key features of the barcode. + * + * @param barcode A bitmap of the captured image. + * @param rawResult The decoded results which contains the points to draw. + */ + private void drawResultPoints(Bitmap barcode, Result rawResult) { + ResultPoint[] points = rawResult.getResultPoints(); + if (points != null && points.length > 0) { + Canvas canvas = new Canvas(barcode); + Paint paint = new Paint(); + paint.setColor(getResources().getColor(R.color.result_image_border)); + paint.setStrokeWidth(3); + paint.setStyle(Paint.Style.STROKE); + Rect border = new Rect(2, 2, barcode.getWidth() - 2, barcode.getHeight() - 2); + canvas.drawRect(border, paint); + + paint.setColor(getResources().getColor(R.color.result_points)); + if (points.length == 2) { + paint.setStrokeWidth(4); + canvas.drawLine(points[0].getX(), points[0].getY(), points[1].getX(), + points[1].getY(), paint); + } else { + paint.setStrokeWidth(10); + for (int x = 0; x < points.length; x++) { + canvas.drawPoint(points[x].getX(), points[x].getY(), paint); + } + } + } + } + + private void handleDecodeForScanIntent(Result rawResult, Bitmap barcode, int duration) { + mViewfinderView.drawResultBitmap(barcode); + + // Since this message will only be shown for a second, just tell the user what kind of + // barcode was found (e.g. contact info) rather than the full contents, which they won't + // have time to read. + ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult); + TextView textView = (TextView) findViewById(R.id.status_text_view); + textView.setGravity(Gravity.CENTER); + textView.setTextSize(18.0f); + textView.setText(getString(resultHandler.getDisplayTitle())); + + mStatusView.setBackgroundColor(getResources().getColor(R.color.transparent)); + + // 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.putExtra(Intents.Scan.RESULT, rawResult.toString()); + intent.putExtra(Intents.Scan.RESULT_FORMAT, rawResult.getBarcodeFormat().toString()); + Message message = Message.obtain(mHandler, R.id.return_scan_result); + message.obj = intent; + mHandler.sendMessageDelayed(message, INTENT_RESULT_DURATION); + } + + /** + * Creates the beep MediaPlayer in advance so that the sound can be triggered with the least + * latency possible. + */ + private void initBeepSound() { + if (mPlayBeep && mMediaPlayer == null) { + mMediaPlayer = new MediaPlayer(); + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_SYSTEM); + mMediaPlayer.setOnCompletionListener(mBeepListener); + + AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.beep); + try { + mMediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), + file.getLength()); + file.close(); + mMediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME); + mMediaPlayer.prepare(); + } catch (IOException e) { + mMediaPlayer = null; + } + } + } + + private void playBeepSound() { + if (mPlayBeep && mMediaPlayer != null) { + mMediaPlayer.start(); + } + } + + private void initCamera(SurfaceHolder surfaceHolder) { + CameraManager.get().openDriver(surfaceHolder); + if (mHandler == null) { + boolean beginScanning = mLastResult == null; + mHandler = new CaptureActivityHandler(this, mDecodeMode, beginScanning); + } + } + + /** + * When the beep has finished playing, rewind to queue up another one. + */ + private final OnCompletionListener mBeepListener = new OnCompletionListener() { + public void onCompletion(MediaPlayer mediaPlayer) { + mediaPlayer.seekTo(0); + } + }; + + private void resetStatusView() { + mResultView.setVisibility(View.GONE); + mStatusView.setVisibility(View.VISIBLE); + mStatusView.setBackgroundColor(getResources().getColor(R.color.status_view)); + mViewfinderView.setVisibility(View.VISIBLE); + + TextView textView = (TextView) findViewById(R.id.status_text_view); + textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + textView.setTextSize(14.0f); + textView.setText(R.string.msg_default_status); + mLastResult = null; + } + + public void drawViewfinder() { + mViewfinderView.drawViewfinder(); + } + +} diff --git a/android/src/com/google/zxing/client/android/CaptureActivityHandler.java b/android/src/com/google/zxing/client/android/CaptureActivityHandler.java new file mode 100755 index 00000000..1dadd81a --- /dev/null +++ b/android/src/com/google/zxing/client/android/CaptureActivityHandler.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.android; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import com.google.zxing.Result; + +/** + * This class handles all the messaging which comprises the state machine for capture. + */ +public class CaptureActivityHandler extends Handler { + + private final CaptureActivity mActivity; + private final DecodeThread mDecodeThread; + private State mState; + + private enum State { + PREVIEW, + SUCCESS, + DONE + } + + CaptureActivityHandler(CaptureActivity activity, String decodeMode, + boolean beginScanning) { + mActivity = activity; + mDecodeThread = new DecodeThread(activity, decodeMode); + mDecodeThread.start(); + mState = State.SUCCESS; + + // Start ourselves capturing previews and decoding. + CameraManager.get().startPreview(); + if (beginScanning) { + restartPreviewAndDecode(); + } + } + + public void handleMessage(Message message) { + switch (message.what) { + case R.id.auto_focus: + // When one auto focus pass finishes, start another. This is the closest thing to + // continuous AF. It does seem to hunt a bit, but I'm not sure what else to do. + if (mState == State.PREVIEW) { + CameraManager.get().requestAutoFocus(this, R.id.auto_focus); + } + break; + case R.id.restart_preview: + restartPreviewAndDecode(); + break; + case R.id.decode_succeeded: + mState = State.SUCCESS; + Bundle bundle = message.getData(); + Bitmap barcode = bundle.getParcelable(DecodeThread.BARCODE_BITMAP); + int duration = message.arg1; + mActivity.handleDecode((Result) message.obj, barcode, duration); + break; + case R.id.decode_failed: + // We're decoding as fast as possible, so when one decode fails, start another. + mState = State.PREVIEW; + CameraManager.get().requestPreviewFrame(mDecodeThread.mHandler, R.id.decode); + break; + case R.id.return_scan_result: + mActivity.setResult(Activity.RESULT_OK, (Intent) message.obj); + mActivity.finish(); + break; + } + } + + public void quitSynchronously() { + mState = State.DONE; + CameraManager.get().stopPreview(); + Message quit = Message.obtain(mDecodeThread.mHandler, R.id.quit); + quit.sendToTarget(); + try { + mDecodeThread.join(); + } catch (InterruptedException e) { + } + + // Be absolutely sure we don't send any queued up messages + removeMessages(R.id.decode_succeeded); + removeMessages(R.id.decode_failed); + } + + private void restartPreviewAndDecode() { + if (mState == State.SUCCESS) { + mState = State.PREVIEW; + CameraManager.get().requestPreviewFrame(mDecodeThread.mHandler, R.id.decode); + CameraManager.get().requestAutoFocus(this, R.id.auto_focus); + mActivity.drawViewfinder(); + } + } + +} diff --git a/android/src/com/google/zxing/client/android/DecodeThread.java b/android/src/com/google/zxing/client/android/DecodeThread.java index 85c0a558..6146e9b9 100755 --- a/android/src/com/google/zxing/client/android/DecodeThread.java +++ b/android/src/com/google/zxing/client/android/DecodeThread.java @@ -40,18 +40,18 @@ final class DecodeThread extends Thread { public static final String BARCODE_BITMAP = "barcode_bitmap"; public Handler mHandler; - private BarcodesCaptureActivity mActivity; + private CaptureActivity mActivity; private MultiFormatReader mMultiFormatReader; - DecodeThread(BarcodesCaptureActivity activity, String mode) { + DecodeThread(CaptureActivity activity, String mode) { mActivity = activity; mMultiFormatReader = new MultiFormatReader(); // The prefs can't change while the thread is running, so pick them up once here. if (mode == null || mode.length() == 0) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); - boolean decode1D = prefs.getBoolean(BarcodesPreferenceActivity.KEY_DECODE_1D, true); - boolean decodeQR = prefs.getBoolean(BarcodesPreferenceActivity.KEY_DECODE_QR, true); + boolean decode1D = prefs.getBoolean(PreferencesActivity.KEY_DECODE_1D, true); + boolean decodeQR = prefs.getBoolean(PreferencesActivity.KEY_DECODE_QR, true); if (decode1D && decodeQR) { setDecodeAllMode(); } else if (decode1D) { diff --git a/android/src/com/google/zxing/client/android/EncodeActivity.java b/android/src/com/google/zxing/client/android/EncodeActivity.java new file mode 100755 index 00000000..0748c158 --- /dev/null +++ b/android/src/com/google/zxing/client/android/EncodeActivity.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.android; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnCancelListener; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +/** + * This class encodes data from an Intent into a QR code, and then displays it full screen so that + * another person can scan it with their device. + */ +public class EncodeActivity extends Activity { + + private QRCodeEncoder mQRCodeEncoder; + private ProgressDialog mProgressDialog; + private boolean mFirstLayout; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + Intent intent = getIntent(); + if (intent != null && (intent.getAction().equals(Intents.Encode.ACTION) || + intent.getAction().equals(Intents.Encode.DEPRECATED_ACTION))) { + setContentView(R.layout.encode); + } else { + finish(); + } + } + + @Override + protected void onResume() { + super.onResume(); + + LinearLayout layout = (LinearLayout) findViewById(R.id.encode_view); + layout.getViewTreeObserver().addOnGlobalLayoutListener(mLayoutListener); + mFirstLayout = true; + } + + /** + * This needs to be delayed until after the first layout so that the view dimensions will be + * available. + */ + public OnGlobalLayoutListener mLayoutListener = new OnGlobalLayoutListener() { + public void onGlobalLayout() { + if (mFirstLayout) { + LinearLayout layout = (LinearLayout) findViewById(R.id.encode_view); + int width = layout.getWidth(); + int height = layout.getHeight(); + int smallerDimension = (width < height) ? width : height; + smallerDimension = smallerDimension * 7 / 8; + + Intent intent = getIntent(); + try { + mQRCodeEncoder = new QRCodeEncoder(EncodeActivity.this, intent); + setTitle(getString(R.string.app_name) + " - " + mQRCodeEncoder.getTitle()); + mQRCodeEncoder.requestBarcode(mHandler, smallerDimension); + mProgressDialog = ProgressDialog.show(EncodeActivity.this, null, + getString(R.string.msg_encode_in_progress), true, true, mCancelListener); + } catch (IllegalArgumentException e) { + showErrorMessage(R.string.msg_encode_contents_failed); + } + mFirstLayout = false; + } + } + }; + + public Handler mHandler = new Handler() { + public void handleMessage(Message message) { + switch (message.what) { + case R.id.encode_succeeded: + mProgressDialog.dismiss(); + mProgressDialog = null; + Bitmap image = (Bitmap) message.obj; + ImageView view = (ImageView) findViewById(R.id.image_view); + view.setImageBitmap(image); + TextView contents = (TextView) findViewById(R.id.contents_text_view); + contents.setText(mQRCodeEncoder.getDisplayContents()); + mQRCodeEncoder = null; + break; + case R.id.encode_failed: + showErrorMessage(R.string.msg_encode_barcode_failed); + mQRCodeEncoder = null; + break; + } + } + }; + + private void showErrorMessage(int message) { + if (mProgressDialog != null) { + mProgressDialog.dismiss(); + mProgressDialog = null; + } + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage(message); + builder.setPositiveButton(R.string.button_ok, mClickListener); + builder.show(); + } + + private OnClickListener mClickListener = new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }; + + private OnCancelListener mCancelListener = new OnCancelListener() { + public void onCancel(DialogInterface dialog) { + finish(); + } + }; + +} diff --git a/android/src/com/google/zxing/client/android/PreferencesActivity.java b/android/src/com/google/zxing/client/android/PreferencesActivity.java new file mode 100755 index 00000000..3ec0548d --- /dev/null +++ b/android/src/com/google/zxing/client/android/PreferencesActivity.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.android; + +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.PreferenceScreen; + +public class PreferencesActivity extends android.preference.PreferenceActivity + implements OnSharedPreferenceChangeListener { + + static final String KEY_DECODE_1D = "preferences_decode_1D"; + static final String KEY_DECODE_QR = "preferences_decode_QR"; + static final String KEY_PLAY_BEEP = "preferences_play_beep"; + + CheckBoxPreference mDecode1D; + CheckBoxPreference mDecodeQR; + CheckBoxPreference mPlayBeep; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + addPreferencesFromResource(R.xml.preferences); + + PreferenceScreen preferences = getPreferenceScreen(); + preferences.getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + mDecode1D = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_1D); + mDecodeQR = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_QR); + mPlayBeep = (CheckBoxPreference) preferences.findPreference(KEY_PLAY_BEEP); + } + + // Prevent the user from turning off both decode options + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals(KEY_DECODE_1D)) { + mDecodeQR.setEnabled(mDecode1D.isChecked()); + mDecodeQR.setChecked(true); + } else if (key.equals(KEY_DECODE_QR)) { + mDecode1D.setEnabled(mDecodeQR.isChecked()); + mDecode1D.setChecked(true); + } + } + +} -- 2.20.1