This is the first version of the ZXing Android client.
[zxing.git] / android / src / com / google / zxing / client / android / BarcodeReaderCaptureActivity.java
1 /*
2  * Copyright (C) 2008 Google Inc.
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.ResultPoint;
21 import com.google.zxing.client.result.ParsedReaderResult;
22 import com.google.zxing.client.result.ParsedReaderResultType;
23
24 import android.app.Activity;
25 import android.content.Context;
26 import android.graphics.PixelFormat;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.os.Message;
30 import android.view.KeyEvent;
31 import android.view.Menu;
32 import android.view.Window;
33 import android.view.WindowManager.LayoutParams;
34
35 public final class BarcodeReaderCaptureActivity extends Activity {
36   
37   private CameraManager cameraManager;
38   private CameraSurfaceView surfaceView;
39   private WorkerThread workerThread;
40   
41   private static final int ABOUT_ID = Menu.FIRST;
42   
43   @Override
44   public void onCreate(Bundle icicle) {
45     super.onCreate(icicle);
46     requestWindowFeature(Window.FEATURE_NO_TITLE);
47
48     // Make sure to create a TRANSLUCENT window. This is required for SurfaceView to work.
49     // Eventually this'll be done by the system automatically.
50     getWindow().setAttributes(new LayoutParams(LayoutParams.APPLICATION_TYPE,
51         LayoutParams.NO_STATUS_BAR_FLAG));
52     getWindow().setFormat(PixelFormat.TRANSLUCENT);
53
54     cameraManager = new CameraManager(getApplication());
55     surfaceView = new CameraSurfaceView(getApplication(), cameraManager);
56     setContentView(surfaceView);
57     workerThread = new WorkerThread(surfaceView, cameraManager, messageHandler);
58     workerThread.requestPreviewLoop();
59     workerThread.start();
60   }
61   
62   @Override
63   protected boolean isFullscreenOpaque() {
64     // Our main window is set to translucent, but we know that we will
65     // fill it with opaque data. Tell the system that so it can perform
66     // some important optimizations.
67     return true;
68   }
69
70   @Override
71   protected void onResume() {
72     super.onResume();
73     cameraManager.openDriver();
74     if (workerThread == null) {
75       workerThread = new WorkerThread(surfaceView, cameraManager, messageHandler);
76       workerThread.requestPreviewLoop();
77       workerThread.start();
78     }
79   }
80
81   @Override
82   protected void onPause() {
83     super.onPause();
84     if (workerThread != null) {
85       workerThread.requestExitAndWait();
86       workerThread = null;
87     }
88     cameraManager.closeDriver();
89   }
90
91   @Override
92   public boolean onKeyDown(int keyCode, KeyEvent event) {
93     if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
94       workerThread.requestStillAndDecode();
95       return true;
96     } else {
97       return super.onKeyDown(keyCode, event);
98     }
99   }
100   
101   @Override
102   public boolean onCreateOptionsMenu(Menu menu) {
103       super.onCreateOptionsMenu(menu);
104       menu.add(0, ABOUT_ID, R.string.menu_about);
105       return true;
106   }
107   
108   @Override
109   public boolean onOptionsItemSelected(Menu.Item item) {
110     switch (item.getId()) {
111       case ABOUT_ID:
112         Context context = getApplication();
113         showAlert(context.getString(R.string.title_about),
114             context.getString(R.string.msg_about),
115             context.getString(R.string.button_ok), null, true, null);
116         break;
117       }
118       return super.onOptionsItemSelected(item);
119   }
120   
121   Handler messageHandler = new Handler() {
122     @Override
123     public void handleMessage(Message message) {
124       switch (message.what) {
125       case R.id.decoding_succeeded_message:
126         handleDecode((Result)message.obj);
127         break;
128       case R.id.decoding_failed_message:
129         Context context = getApplication();
130         showAlert(context.getString(R.string.title_no_barcode_detected),
131             context.getString(R.string.msg_no_barcode_detected),
132             context.getString(R.string.button_ok), null, true, null);
133         break;
134       }
135     }
136   };
137   
138   public void restartPreview() {
139     workerThread.requestPreviewLoop();
140   }
141   
142   // TODO(dswitkin): These deprecated showAlert calls need to be updated.
143   private void handleDecode(Result rawResult) {
144     ResultPoint[] points = rawResult.getResultPoints();
145     if (points != null && points.length > 0) {
146       surfaceView.drawResultPoints(points);
147     }
148
149     Context context = getApplication();
150     ParsedReaderResult readerResult = ParsedReaderResult.parseReaderResult(rawResult.getText());
151     Handler handler = new ResultHandler(this, readerResult);
152     if (canBeHandled(readerResult.getType())) {
153       // Can be handled by some external app; ask if the user wants to
154       // proceed first though
155       Message yesMessage = handler.obtainMessage(R.string.button_yes);
156       Message noMessage = handler.obtainMessage(R.string.button_no);
157       showAlert(context.getString(getDialogTitleID(readerResult.getType())),
158           readerResult.getDisplayResult(), context.getString(R.string.button_yes),
159           yesMessage, context.getString(R.string.button_no), noMessage, true, noMessage);
160     } else {
161       // Just show information to user
162       Message okMessage = handler.obtainMessage(R.string.button_ok);
163       showAlert(context.getString(R.string.title_barcode_detected),
164           readerResult.getDisplayResult(), context.getString(R.string.button_ok), okMessage, null,
165           null, true, okMessage);
166     }
167   }
168
169   private static boolean canBeHandled(ParsedReaderResultType type) {
170     return type != ParsedReaderResultType.TEXT;
171   }
172
173   private static int getDialogTitleID(ParsedReaderResultType type) {
174     if (type == ParsedReaderResultType.ADDRESSBOOK) {
175       return R.string.title_add_contact;
176     } else if (type == ParsedReaderResultType.BOOKMARK) {
177       return R.string.title_open_url;
178     } else if (type == ParsedReaderResultType.EMAIL || type == ParsedReaderResultType.EMAIL_ADDRESS) {
179       return R.string.title_compose_email;
180     } else if (type == ParsedReaderResultType.UPC) {
181       return R.string.title_lookup_barcode;
182     } else if (type == ParsedReaderResultType.URI) {
183       return R.string.title_open_url;
184     } else {
185       return R.string.title_barcode_detected;
186     }
187   }
188   
189 }