1 /* 2 * Copyright (C) 2008 ZXing authors 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 package com.google.zxing.client.android; 18 19 import com.google.zxing.Result; 20 import com.google.zxing.client.android.camera.CameraManager; 21 22 import android.app.Activity; 23 import android.content.Intent; 24 import android.graphics.Bitmap; 25 import android.net.Uri; 26 import android.os.Bundle; 27 import android.os.Handler; 28 import android.os.Message; 29 import android.util.Log; 30 31 /** 32 * This class handles all the messaging which comprises the state machine for capture. 33 * 34 * @author dswitkin (at) google.com (Daniel Switkin) 35 */ 36 public final class CaptureActivityHandler extends Handler { 37 38 private static final String TAG = CaptureActivityHandler.class.getSimpleName(); 39 40 private final CaptureActivity activity; 41 private final DecodeThread decodeThread; 42 private State state; 43 private final CameraManager cameraManager; 44 45 private enum State { 46 PREVIEW, 47 SUCCESS, 48 DONE 49 } 50 51 CaptureActivityHandler(CaptureActivity activity, 52 String characterSet, 53 CameraManager cameraManager) { 54 this.activity = activity; 55 decodeThread = new DecodeThread(activity, characterSet, 56 new ViewfinderResultPointCallback(activity.getViewfinderView())); 57 decodeThread.start(); 58 state = State.SUCCESS; 59 60 // Start ourselves capturing previews and decoding. 61 this.cameraManager = cameraManager; 62 cameraManager.startPreview(); 63 restartPreviewAndDecode(); 64 } 65 66 @Override 67 public void handleMessage(Message message) { 68 if (message.what == R.id.auto_focus) { 69 //Log.d(TAG, "Got auto-focus message"); 70 // When one auto focus pass finishes, start another. This is the closest thing to 71 // continuous AF. It does seem to hunt a bit, but I'm not sure what else to do. 72 if (state == State.PREVIEW) { 73 cameraManager.requestAutoFocus(this, R.id.auto_focus); 74 } 75 } else if (message.what == R.id.restart_preview) { 76 Log.d(TAG, "Got restart preview message"); 77 restartPreviewAndDecode(); 78 } else if (message.what == R.id.decode_succeeded) { 79 Log.d(TAG, "Got decode succeeded message"); 80 state = State.SUCCESS; 81 Bundle bundle = message.getData(); 82 Bitmap barcode = bundle == null ? null : 83 (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP); 84 activity.handleDecode((Result) message.obj, barcode); 85 } else if (message.what == R.id.decode_failed) { 86 // We're decoding as fast as possible, so when one decode fails, start another. 87 state = State.PREVIEW; 88 cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode); 89 } else if (message.what == R.id.return_scan_result) { 90 Log.d(TAG, "Got return scan result message"); 91 activity.setResult(Activity.RESULT_OK, (Intent) message.obj); 92 activity.finish(); 93 } else if (message.what == R.id.launch_product_query) { 94 Log.d(TAG, "Got product query message"); 95 String url = (String) message.obj; 96 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 97 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 98 activity.startActivity(intent); 99 } 100 } 101 102 public void quitSynchronously() { 103 state = State.DONE; 104 cameraManager.stopPreview(); 105 Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit); 106 quit.sendToTarget(); 107 try { 108 // Wait at most half a second; should be enough time, and onPause() will timeout quickly 109 decodeThread.join(500L); 110 } catch (InterruptedException e) { 111 // continue 112 } 113 114 // Be absolutely sure we don't send any queued up messages 115 removeMessages(R.id.decode_succeeded); 116 removeMessages(R.id.decode_failed); 117 } 118 119 private void restartPreviewAndDecode() { 120 if (state == State.SUCCESS) { 121 state = State.PREVIEW; 122 cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode); 123 cameraManager.requestAutoFocus(this, R.id.auto_focus); 124 activity.drawViewfinder(); 125 } 126 } 127 128 } 129