public void quitSynchronously() {
    state = State.DONE;
    cameraManager.stopPreview();
    Message quit = Message.obtain(decodeThread.getHandler(), DecodeStatus.QUIT);
    quit.sendToTarget();
    try {
      // Wait at most half a second; should be enough time, and onPause()
      // will connectTimeout quickly
      decodeThread.join(500L);
    } catch (InterruptedException e) {
      // continue
    }

    // Be absolutely sure we don't send any queued up messages
    removeMessages(DecodeStatus.DECODE_SUCCEEDED);
    removeMessages(DecodeStatus.DECODE_FAILED);
  }
  public CaptureActivityHandler(
      CaptureActivity activity, CameraManager cameraManager, int decodeMode) {
    this.activity = activity;
    decodeThread = new DecodeThread(activity, decodeMode);
    decodeThread.start();
    state = State.SUCCESS;

    // Start ourselves capturing previews and decoding.
    this.cameraManager = cameraManager;
    cameraManager.startPreview();
    restartPreviewAndDecode();
  }
  @Override
  public void handleMessage(Message message) {
    switch (message.what) {
      case DecodeStatus.RESTART_PREVIEW:
        restartPreviewAndDecode();
        break;
      case DecodeStatus.DECODE_SUCCEEDED:
        state = State.SUCCESS;
        Bundle bundle = message.getData();

        activity.handleDecode((Result) message.obj, bundle);
        break;
      case DecodeStatus.DECODE_FAILED:
        // We're decoding as fast as possible, so when one decode fails,
        // start another.
        state = State.PREVIEW;
        cameraManager.requestPreviewFrame(decodeThread.getHandler(), DecodeStatus.DECODE);
        break;
      case DecodeStatus.RETURN_SCAN_RESULT:
        activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
        activity.finish();
        break;
    }
  }
 private void restartPreviewAndDecode() {
   if (state == State.SUCCESS) {
     state = State.PREVIEW;
     cameraManager.requestPreviewFrame(decodeThread.getHandler(), DecodeStatus.DECODE);
   }
 }