17620644768ffc235607b3a94671e49518c18686fBryan Mawhinney/*
27620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Copyright (C) 2008 ZXing authors
37620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
47620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Licensed under the Apache License, Version 2.0 (the "License"); you may not
57620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * use this file except in compliance with the License. You may obtain a copy of
67620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * the License at
77620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
87620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * http://www.apache.org/licenses/LICENSE-2.0
97620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
107620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Unless required by applicable law or agreed to in writing, software
117620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
127620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
137620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * License for the specific language governing permissions and limitations under
147620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * the License.
157620644768ffc235607b3a94671e49518c18686fBryan Mawhinney */
167620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
177620644768ffc235607b3a94671e49518c18686fBryan Mawhinneypackage com.google.zxing.client.android;
187620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
197620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.BarcodeFormat;
207620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.Result;
217620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.ResultPoint;
227620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport com.google.zxing.client.android.camera.CameraManager;
237620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
247620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.app.Activity;
257620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.app.AlertDialog;
267620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.content.Intent;
277620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.graphics.Bitmap;
287620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.graphics.Canvas;
297620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.graphics.Paint;
307620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.graphics.Rect;
317620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.os.Bundle;
327620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.os.Handler;
337620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.util.Log;
347620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.view.KeyEvent;
357620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.view.SurfaceHolder;
367620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.view.SurfaceView;
377620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.view.View;
387620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.view.Window;
397620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.view.WindowManager;
407620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.widget.TextView;
417620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
427620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.io.IOException;
437620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
447620644768ffc235607b3a94671e49518c18686fBryan Mawhinney/**
457620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * This activity opens the camera and does the actual scanning on a background
467620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * thread. It draws a viewfinder to help the user place the barcode correctly,
477620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * shows feedback as the image processing is happening, and then overlays the
487620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * results when a scan is successful.
497620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
507620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * @author dswitkin@google.com (Daniel Switkin)
517620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * @author Sean Owen
527620644768ffc235607b3a94671e49518c18686fBryan Mawhinney */
537620644768ffc235607b3a94671e49518c18686fBryan Mawhinneypublic final class CaptureActivity extends Activity implements SurfaceHolder.Callback {
547620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
557620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static final String LOG_TAG = CaptureActivity.class.getCanonicalName();
567620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
577620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private CameraManager cameraManager;
587620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private CaptureActivityHandler handler;
597620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private ViewfinderView viewfinderView;
607620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private TextView statusView;
617620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private boolean hasSurface;
627620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private String characterSet;
637620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private InactivityTimer inactivityTimer;
647620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
657620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  ViewfinderView getViewfinderView() {
667620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    return viewfinderView;
677620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
687620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
697620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public Handler getHandler() {
707620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    return handler;
717620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
727620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
737620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  CameraManager getCameraManager() {
747620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    return cameraManager;
757620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
767620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
777620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  @Override
787620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void onCreate(Bundle icicle) {
797620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    super.onCreate(icicle);
807620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
817620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Window window = getWindow();
827620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
837620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    setContentView(R.layout.capture);
847620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
857620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    statusView = (TextView) findViewById(R.id.status_view);
867620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    handler = null;
877620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    hasSurface = false;
887620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    inactivityTimer = new InactivityTimer(this);
897620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
907620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
917620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  @Override
927620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  protected void onResume() {
937620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    super.onResume();
947620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
957620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    // CameraManager must be initialized here, not in onCreate(). This is
967620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    // necessary because we don't want to open the camera driver and measure the
977620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    // screen size if we're going to show the help on first launch. That led to
987620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    // bugs where the scanning rectangle was the wrong size and partially off
997620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    // screen.
1007620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    cameraManager = new CameraManager(getApplication());
1017620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
1027620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    viewfinderView.setCameraManager(cameraManager);
1037620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1047620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    resetStatusView();
1057620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1067620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
1077620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    SurfaceHolder surfaceHolder = surfaceView.getHolder();
1087620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (hasSurface) {
1097620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // The activity was paused but not stopped, so the surface still exists.
1107620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // Therefore
1117620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // surfaceCreated() won't be called, so init the camera here.
1127620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      initCamera(surfaceHolder);
1137620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } else {
1147620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // Install the callback and wait for surfaceCreated() to init the camera.
1157620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      surfaceHolder.addCallback(this);
1167620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
1177620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1187620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1197620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Intent intent = getIntent();
1207620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    String action = intent == null ? null : intent.getAction();
1217620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    String dataString = intent == null ? null : intent.getDataString();
1227620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (intent != null && action != null) {
1237620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (action.equals(Intents.Scan.ACTION)) {
1247620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        if (intent.hasExtra(Intents.Scan.WIDTH) && intent.hasExtra(Intents.Scan.HEIGHT)) {
1257620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          int width = intent.getIntExtra(Intents.Scan.WIDTH, 0);
1267620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          int height = intent.getIntExtra(Intents.Scan.HEIGHT, 0);
1277620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          if (width > 0 && height > 0) {
1287620644768ffc235607b3a94671e49518c18686fBryan Mawhinney            cameraManager.setManualFramingRect(width, height);
1297620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          }
1307620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        }
1317620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
1327620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      characterSet = intent.getStringExtra(Intents.Scan.CHARACTER_SET);
1337620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } else {
1347620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      finish();
1357620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1367620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1377620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    inactivityTimer.onResume();
1387620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1397620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1407620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  @Override
1417620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  protected void onPause() {
1427620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (handler != null) {
1437620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      handler.quitSynchronously();
1447620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      handler = null;
1457620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1467620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    inactivityTimer.onPause();
1477620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    cameraManager.closeDriver();
1487620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (!hasSurface) {
1497620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
1507620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      SurfaceHolder surfaceHolder = surfaceView.getHolder();
1517620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      surfaceHolder.removeCallback(this);
1527620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1537620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    super.onPause();
1547620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1557620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1567620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  @Override
1577620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  protected void onDestroy() {
1587620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    inactivityTimer.shutdown();
1597620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    super.onDestroy();
1607620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1617620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1627620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  @Override
1637620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public boolean onKeyDown(int keyCode, KeyEvent event) {
1647620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (keyCode == KeyEvent.KEYCODE_BACK) {
1657620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      setResult(RESULT_CANCELED);
1667620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      finish();
1677620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      return true;
1687620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } else if (keyCode == KeyEvent.KEYCODE_FOCUS || keyCode == KeyEvent.KEYCODE_CAMERA) {
1697620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // Handle these events so they don't launch the Camera app
1707620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      return true;
1717620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1727620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    return super.onKeyDown(keyCode, event);
1737620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1747620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1757620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void surfaceCreated(SurfaceHolder holder) {
1767620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (holder == null) {
1777620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Log.e(LOG_TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
1787620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1797620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (!hasSurface) {
1807620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      hasSurface = true;
1817620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      initCamera(holder);
1827620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1837620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1847620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1857620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void surfaceDestroyed(SurfaceHolder holder) {
1867620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    hasSurface = false;
1877620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1887620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1897620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
1907620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1917620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1927620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1937620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  /**
1947620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * A valid barcode has been found, so give an indication of success and show
1957620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * the results.
1967620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   *
1977620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * @param rawResult The contents of the barcode.
1987620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * @param barcode A greyscale bitmap of the camera data which was decoded.
1997620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   */
2007620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void handleDecode(Result rawResult, Bitmap barcode) {
2017620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    inactivityTimer.onActivity();
2027620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
2037620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (barcode == null) {
2047620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Log.e(LOG_TAG, "Barcode not recognized");
2057620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      setResult(RESULT_CANCELED, null);
2067620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } else {
2077620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      drawResultPoints(barcode, rawResult);
2087620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Log.d(LOG_TAG, "Barcode is: " + rawResult.getText());
2097620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Intent result = new Intent();
2107620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      result.putExtra("SCAN_RESULT", rawResult.getText());
2117620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      setResult(RESULT_OK, result);
2127620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
2137620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    finish();
2147620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
2157620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
2167620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  /**
2177620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * Superimpose a line for 1D or dots for 2D to highlight the key features of
2187620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * the barcode.
2197620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   *
2207620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * @param barcode A bitmap of the captured image.
2217620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * @param rawResult The decoded results which contains the points to draw.
2227620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   */
2237620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private void drawResultPoints(Bitmap barcode, Result rawResult) {
2247620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    ResultPoint[] points = rawResult.getResultPoints();
2257620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (points != null && points.length > 0) {
2267620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Canvas canvas = new Canvas(barcode);
2277620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Paint paint = new Paint();
2287620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      paint.setColor(getResources().getColor(R.color.result_image_border));
2297620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      paint.setStrokeWidth(3.0f);
2307620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      paint.setStyle(Paint.Style.STROKE);
2317620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Rect border = new Rect(2, 2, barcode.getWidth() - 2, barcode.getHeight() - 2);
2327620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      canvas.drawRect(border, paint);
2337620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
2347620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      paint.setColor(getResources().getColor(R.color.result_points));
2357620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (points.length == 2) {
2367620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        paint.setStrokeWidth(4.0f);
2377620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        drawLine(canvas, paint, points[0], points[1]);
2387620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      } else if (points.length == 4 && (rawResult.getBarcodeFormat() == BarcodeFormat.UPC_A
2397620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          || rawResult.getBarcodeFormat() == BarcodeFormat.EAN_13)) {
2407620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        // Hacky special case -- draw two lines, for the barcode and metadata
2417620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        drawLine(canvas, paint, points[0], points[1]);
2427620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        drawLine(canvas, paint, points[2], points[3]);
2437620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      } else {
2447620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        paint.setStrokeWidth(10.0f);
2457620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        for (ResultPoint point : points) {
2467620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          canvas.drawPoint(point.getX(), point.getY(), paint);
2477620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        }
2487620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
2497620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
2507620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
2517620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
2527620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static void drawLine(Canvas canvas, Paint paint, ResultPoint a, ResultPoint b) {
2537620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    canvas.drawLine(a.getX(), a.getY(), b.getX(), b.getY(), paint);
2547620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
2557620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
2567620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private void initCamera(SurfaceHolder surfaceHolder) {
2577620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    try {
2587620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      cameraManager.openDriver(surfaceHolder);
2597620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // Creating the handler starts the preview, which can also throw a
2607620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // RuntimeException.
2617620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (handler == null) {
2627620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        handler = new CaptureActivityHandler(this, characterSet, cameraManager);
2637620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
2647620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } catch (IOException ioe) {
2657620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Log.w(LOG_TAG, ioe);
2667620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      displayFrameworkBugMessageAndExit();
2677620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } catch (RuntimeException e) {
2687620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // Barcode Scanner has seen crashes in the wild of this variety:
2697620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      // java.?lang.?RuntimeException: Fail to connect to camera service
2707620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Log.w(LOG_TAG, "Unexpected error initializing camera", e);
2717620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      displayFrameworkBugMessageAndExit();
2727620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
2737620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
2747620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
2757620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private void displayFrameworkBugMessageAndExit() {
2767620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    AlertDialog.Builder builder = new AlertDialog.Builder(this);
2777620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    builder.setTitle("");
2787620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    builder.setMessage(getString(R.string.msg_camera_framework_bug));
2797620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    builder.setPositiveButton(android.R.string.ok, new FinishListener(this));
2807620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    builder.setOnCancelListener(new FinishListener(this));
2817620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    builder.show();
2827620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
2837620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
2847620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private void resetStatusView() {
2857620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    statusView.setText(R.string.msg_default_status);
2867620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    statusView.setVisibility(View.VISIBLE);
2877620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    viewfinderView.setVisibility(View.VISIBLE);
2887620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
2897620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
2907620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void drawViewfinder() {
2917620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    viewfinderView.drawViewfinder();
2927620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
2937620644768ffc235607b3a94671e49518c18686fBryan Mawhinney}
294