2 * Copyright (C) 2008 Google Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.barcodes;
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.DialogInterface;
22 import android.content.Intent;
23 import android.content.SharedPreferences;
24 import android.content.res.AssetFileDescriptor;
25 import android.media.MediaPlayer;
26 import android.media.AudioManager;
27 import android.media.MediaPlayer.OnCompletionListener;
28 import android.net.Uri;
29 import android.os.Bundle;
30 import android.os.Message;
31 import android.preference.PreferenceManager;
32 import android.view.KeyEvent;
33 import android.view.Menu;
34 import android.view.MenuItem;
35 import android.view.SurfaceHolder;
36 import android.view.SurfaceView;
37 import android.view.View;
38 import android.view.Window;
39 import android.view.WindowManager;
40 import android.widget.Button;
41 import android.widget.TextView;
42 import com.google.zxing.Result;
43 import com.google.zxing.ResultPoint;
44 import com.google.zxing.client.result.ParsedResult;
46 import java.io.IOException;
49 * The barcode reader activity itself. This is loosely based on the CameraPreview
50 * example included in the Android SDK.
52 public final class BarcodesCaptureActivity extends Activity implements SurfaceHolder.Callback {
54 private static final int SETTINGS_ID = Menu.FIRST;
55 private static final int HELP_ID = Menu.FIRST + 1;
56 private static final int ABOUT_ID = Menu.FIRST + 2;
58 public BarcodesCaptureActivityHandler mHandler;
60 private ViewfinderView mViewfinderView;
61 private MediaPlayer mMediaPlayer;
62 private String mLastResult;
63 private boolean mPlayBeep;
64 private boolean mScanIntent;
65 private String mDecodeMode;
68 public void onCreate(Bundle icicle) {
69 super.onCreate(icicle);
71 Window window = getWindow();
72 window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
73 setContentView(R.layout.capture);
75 CameraManager.init(getApplication());
76 mViewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
79 SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
80 SurfaceHolder surfaceHolder = surfaceView.getHolder();
81 surfaceHolder.addCallback(this);
82 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
86 protected void onResume() {
90 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
91 mPlayBeep = prefs.getBoolean(BarcodesPreferenceActivity.KEY_PLAY_BEEP, true);
94 Intent intent = getIntent();
95 if (intent != null && intent.getAction().equals(Intents.Scan.ACTION)) {
97 mDecodeMode = intent.getStringExtra(Intents.Scan.MODE);
105 protected void onPause() {
107 if (mHandler != null) {
108 mHandler.quitSynchronously();
111 CameraManager.get().closeDriver();
115 public boolean onKeyDown(int keyCode, KeyEvent event) {
116 if (keyCode == KeyEvent.KEYCODE_BACK) {
118 setResult(RESULT_CANCELED);
122 } else if (keyCode == KeyEvent.KEYCODE_FOCUS || keyCode == KeyEvent.KEYCODE_CAMERA) {
123 // Handle these events so they don't launch the Camera app
126 return super.onKeyDown(keyCode, event);
130 public boolean onCreateOptionsMenu(Menu menu) {
131 super.onCreateOptionsMenu(menu);
132 menu.add(0, SETTINGS_ID, 0, R.string.menu_settings)
133 .setIcon(android.R.drawable.ic_menu_preferences);
134 menu.add(0, HELP_ID, 0, R.string.menu_help)
135 .setIcon(android.R.drawable.ic_menu_help);
136 menu.add(0, ABOUT_ID, 0, R.string.menu_about)
137 .setIcon(android.R.drawable.ic_menu_info_details);
142 public boolean onOptionsItemSelected(MenuItem item) {
143 switch (item.getItemId()) {
145 Intent intent = new Intent(Intent.ACTION_VIEW);
146 intent.setClassName(this, BarcodesPreferenceActivity.class.getName());
147 startActivity(intent);
151 AlertDialog.Builder builder = new AlertDialog.Builder(this);
152 builder.setTitle(R.string.title_help);
153 builder.setMessage(R.string.msg_help);
154 builder.setPositiveButton(R.string.button_ok, null);
159 AlertDialog.Builder builder = new AlertDialog.Builder(this);
160 builder.setTitle(R.string.title_about);
161 builder.setMessage(getString(R.string.msg_about) + "\n\n" + getString(R.string.zxing_url));
162 builder.setIcon(R.drawable.zxing_icon);
163 builder.setPositiveButton(R.string.button_open_browser, mAboutListener);
164 builder.setNegativeButton(R.string.button_cancel, null);
169 return super.onOptionsItemSelected(item);
172 private final DialogInterface.OnClickListener mAboutListener = new DialogInterface.OnClickListener() {
173 public void onClick(android.content.DialogInterface dialogInterface, int i) {
174 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.zxing_url)));
175 startActivity(intent);
179 public void surfaceCreated(SurfaceHolder holder) {
180 CameraManager.get().openDriver(holder);
181 if (mHandler == null) {
182 mHandler = new BarcodesCaptureActivityHandler(this, mDecodeMode);
186 public void surfaceDestroyed(SurfaceHolder holder) {
190 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
195 * A valid barcode has been found, so give an indication of success and show the results.
197 * @param rawResult The contents of the barcode.
198 * @param duration How long the decoding took in milliseconds.
200 public void handleDecode(Result rawResult, int duration) {
201 if (!rawResult.toString().equals(mLastResult)) {
202 mLastResult = rawResult.toString();
205 ResultPoint[] points = rawResult.getResultPoints();
206 if (points != null && points.length > 0) {
207 mViewfinderView.drawResultPoints(points);
210 TextView textView = (TextView) findViewById(R.id.status_text_view);
211 ParsedResult result = ResultHandler.parseResult(rawResult);
212 String displayResult = result.getDisplayResult();
213 displayResult = displayResult.replace("\r", "");
214 textView.setText(displayResult);
217 Button actionButton = (Button) findViewById(R.id.status_action_button);
218 int buttonText = ResultHandler.getActionButtonText(result.getType());
219 if (buttonText != 0) {
220 actionButton.setVisibility(View.VISIBLE);
221 actionButton.setText(buttonText);
222 ResultHandler resultHandler = new ResultHandler(this, result);
223 actionButton.setOnClickListener(resultHandler);
224 actionButton.requestFocus();
226 actionButton.setVisibility(View.GONE);
230 View statusView = findViewById(R.id.status_view);
231 statusView.setBackgroundColor(getResources().getColor(R.color.result_points));
233 // Show the green finder patterns briefly, then either return the result or go back to
234 // continuous scanning.
236 Intent intent = new Intent(Intents.Scan.ACTION);
237 intent.putExtra(Intents.Scan.RESULT, rawResult.toString());
238 intent.putExtra(Intents.Scan.RESULT_FORMAT, rawResult.getBarcodeFormat().toString());
239 Message message = Message.obtain(mHandler, R.id.return_scan_result);
240 message.obj = intent;
241 mHandler.sendMessageDelayed(message, 1000);
243 Message message = Message.obtain(mHandler, R.id.restart_preview);
244 mHandler.sendMessageDelayed(message, 2000);
246 } else if (mHandler != null) {
247 Message message = Message.obtain(mHandler, R.id.restart_preview);
248 message.sendToTarget();
253 * Creates the beep MediaPlayer in advance so that the sound can be triggered with the least
256 private void initBeepSound() {
257 if (mPlayBeep && mMediaPlayer == null) {
258 mMediaPlayer = new MediaPlayer();
259 mMediaPlayer.setAudioStreamType(AudioManager.STREAM_SYSTEM);
260 mMediaPlayer.setOnCompletionListener(mBeepListener);
262 AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.beep);
264 mMediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(),
267 mMediaPlayer.setVolume(0.15f, 0.15f);
268 mMediaPlayer.prepare();
269 } catch (IOException e) {
275 private void playBeepSound() {
276 if (mPlayBeep && mMediaPlayer != null) {
277 mMediaPlayer.start();
282 * When the beep has finished playing, rewind to queue up another one.
284 private final OnCompletionListener mBeepListener = new OnCompletionListener() {
285 public void onCompletion(MediaPlayer mediaPlayer) {
286 mediaPlayer.seekTo(0);
290 private void resetStatusView() {
291 resetStatusViewColor();
292 TextView textView = (TextView) findViewById(R.id.status_text_view);
293 textView.setText(R.string.msg_default_status);
294 Button actionButton = (Button) findViewById(R.id.status_action_button);
295 actionButton.setVisibility(View.GONE);
299 public void resetStatusViewColor() {
300 View statusView = findViewById(R.id.status_view);
301 statusView.setBackgroundColor(getResources().getColor(R.color.status_view));
304 public void drawViewfinder() {
305 mViewfinderView.drawViewfinder();