Small style stuff
[zxing.git] / javame / src / com / google / zxing / client / j2me / ZXingMIDlet.java
1 /*\r
2  * Copyright 2007 ZXing authors\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 package com.google.zxing.client.j2me;\r
18 \r
19 import com.google.zxing.Result;\r
20 import com.google.zxing.client.result.EmailAddressParsedResult;\r
21 import com.google.zxing.client.result.ParsedResult;\r
22 import com.google.zxing.client.result.ParsedResultType;\r
23 import com.google.zxing.client.result.ResultParser;\r
24 import com.google.zxing.client.result.SMSParsedResult;\r
25 import com.google.zxing.client.result.TelParsedResult;\r
26 import com.google.zxing.client.result.ProductParsedResult;\r
27 import com.google.zxing.client.result.URIParsedResult;\r
28 \r
29 import javax.microedition.lcdui.Image;\r
30 import javax.microedition.io.ConnectionNotFoundException;\r
31 import javax.microedition.lcdui.Alert;\r
32 import javax.microedition.lcdui.AlertType;\r
33 import javax.microedition.lcdui.Canvas;\r
34 import javax.microedition.lcdui.Command;\r
35 import javax.microedition.lcdui.CommandListener;\r
36 import javax.microedition.lcdui.Display;\r
37 import javax.microedition.lcdui.Displayable;\r
38 import javax.microedition.media.Manager;\r
39 import javax.microedition.media.MediaException;\r
40 import javax.microedition.media.Player;\r
41 import javax.microedition.media.control.VideoControl;\r
42 import javax.microedition.midlet.MIDlet;\r
43 import javax.microedition.midlet.MIDletStateChangeException;\r
44 import java.io.IOException;\r
45 import java.util.Vector;\r
46 \r
47 /**\r
48  * <p>The actual reader application {@link MIDlet}.</p>\r
49  *\r
50  * @author Sean Owen\r
51  * @author Simon Flannery\r
52  */\r
53 public final class ZXingMIDlet extends MIDlet {\r
54 \r
55   private static final int ALERT_TIMEOUT_MS = 5 * 1000;\r
56 \r
57   private Canvas canvas;\r
58   private Player player;\r
59   private VideoControl videoControl;\r
60   private Alert confirmation;\r
61   private Alert alert;\r
62   private Menu history;\r
63   private Vector resultHistory;\r
64 \r
65   Displayable getCanvas() {\r
66     return canvas;\r
67   }\r
68 \r
69   Player getPlayer() {\r
70     return player;\r
71   }\r
72 \r
73   VideoControl getVideoControl() {\r
74     return videoControl;\r
75   }\r
76 \r
77   static MultimediaManager buildMultimediaManager() {\r
78     return new AdvancedMultimediaManager();\r
79     // Comment line above / uncomment below to make the basic version\r
80     // return new DefaultMultimediaManager();\r
81   }\r
82 \r
83   protected void startApp() throws MIDletStateChangeException {\r
84     try {\r
85       Image image = Image.createImage("/res/zxing-icon.png");\r
86       Displayable splash = new SplashThread(this, 2000, image);\r
87       Display.getDisplay(this).setCurrent(splash);\r
88 \r
89       resultHistory = new Vector(5);\r
90       history = new Menu(this, "Scan History", "Use");\r
91 \r
92       player = createPlayer();\r
93       player.realize();\r
94       MultimediaManager multimediaManager = buildMultimediaManager();\r
95       multimediaManager.setZoom(player);\r
96       multimediaManager.setExposure(player);\r
97       multimediaManager.setFlash(player);\r
98       videoControl = (VideoControl) player.getControl("VideoControl");\r
99       canvas = new VideoCanvas(this);\r
100       canvas.setFullScreenMode(true);\r
101       videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas);\r
102       videoControl.setDisplayLocation(0, 0);\r
103       videoControl.setDisplaySize(canvas.getWidth(), canvas.getHeight());\r
104     } catch (IOException ioe) {\r
105       throw new MIDletStateChangeException(ioe.toString());\r
106     } catch (MediaException me) {\r
107       throw new MIDletStateChangeException(me.toString());\r
108     }\r
109 \r
110     // Set up one confirmation and alert object to re-use\r
111     confirmation = new Alert(null);\r
112     confirmation.setType(AlertType.CONFIRMATION);\r
113     confirmation.setTimeout(ALERT_TIMEOUT_MS);\r
114     Command yes = new Command("Yes", Command.OK, 1);\r
115     confirmation.addCommand(yes);\r
116     Command no = new Command("No", Command.CANCEL, 1);\r
117     confirmation.addCommand(no);\r
118     alert = new Alert(null);\r
119     alert.setTimeout(ALERT_TIMEOUT_MS);\r
120   }\r
121 \r
122   void splashDone() {\r
123     try {\r
124       videoControl.setVisible(true);\r
125       player.start();\r
126     } catch (MediaException me) {\r
127       showError(me);\r
128     }\r
129     Display.getDisplay(this).setCurrent(canvas);\r
130   }\r
131 \r
132   private static Player createPlayer() throws IOException, MediaException {\r
133     // Try a workaround for Nokias, which want to use capture://image in some cases\r
134     Player player = null;\r
135     String platform = System.getProperty("microedition.platform");\r
136     if (platform != null && platform.indexOf("Nokia") >= 0) {\r
137       try {\r
138         player = Manager.createPlayer("capture://image");\r
139       } catch (MediaException me) {\r
140         // if this fails, just continue with capture://video\r
141       } catch (NullPointerException npe) { // Thanks webblaz... for this improvement:\r
142         // The Nokia 2630 throws this if image/video capture is not supported\r
143         // We should still try to continue\r
144       } catch (Error e) {\r
145         // Ugly, but, it seems the Nokia N70 throws "java.lang.Error: 136" here\r
146         // We should still try to continue\r
147       }\r
148     }\r
149     if (player == null) {\r
150       try {\r
151         player = Manager.createPlayer("capture://video");\r
152       } catch (NullPointerException npe) {\r
153         // The Nokia 2630 throws this if image/video capture is not supported\r
154         throw new MediaException("Image/video capture not supported on this phone");\r
155       }\r
156     }\r
157     return player;\r
158   }\r
159 \r
160   protected void pauseApp() {\r
161     if (player != null) {\r
162       try {\r
163         player.stop();\r
164       } catch (MediaException me) {\r
165         // continue?\r
166         showError(me);\r
167       }\r
168     }\r
169   }\r
170 \r
171   protected void destroyApp(boolean unconditional) {\r
172     if (player != null) {\r
173       videoControl = null;\r
174       try {\r
175         player.stop();\r
176       } catch (MediaException me) {\r
177         // continue\r
178       }\r
179       player.deallocate();\r
180       player.close();\r
181       player = null;\r
182     }\r
183   }\r
184 \r
185   void stop() {\r
186     destroyApp(false);\r
187     notifyDestroyed();\r
188   }\r
189 \r
190   void historyRequest() {\r
191     Display.getDisplay(this).setCurrent(history);\r
192   }\r
193 \r
194   // Convenience methods to show dialogs\r
195 \r
196   private void showOpenURL(String title, String display, final String uri) {\r
197     confirmation.setTitle(title);\r
198     confirmation.setString(display);\r
199     CommandListener listener = new CommandListener() {\r
200       public void commandAction(Command command, Displayable displayable) {\r
201         if (command.getCommandType() == Command.OK) {\r
202           try {\r
203             platformRequest(uri);\r
204           } catch (ConnectionNotFoundException cnfe) {\r
205             showError(cnfe);\r
206           } finally {\r
207             stop();\r
208           }\r
209         } else {\r
210           // cancel\r
211           Display.getDisplay(ZXingMIDlet.this).setCurrent(getCanvas());\r
212         }\r
213       }\r
214     };\r
215     confirmation.setCommandListener(listener);\r
216     showAlert(confirmation);\r
217   }\r
218 \r
219   private void showAlert(String title, String text) {\r
220     alert.setTitle(title);\r
221     alert.setString(text);\r
222     alert.setType(AlertType.INFO);\r
223     showAlert(alert);\r
224   }\r
225 \r
226   void showError(Throwable t) {\r
227     String message = t.getMessage();\r
228     if (message != null && message.length() > 0) {\r
229       showError(message);\r
230     } else {\r
231       showError(t.toString());\r
232     }\r
233   }\r
234 \r
235   void showError(String message) {\r
236     alert.setTitle("Error");\r
237     alert.setString(message);\r
238     alert.setType(AlertType.ERROR);\r
239     showAlert(alert);\r
240   }\r
241 \r
242   private void showAlert(Alert alert) {\r
243     Display display = Display.getDisplay(this);\r
244     display.setCurrent(alert, canvas);\r
245   }\r
246 \r
247   void barcodeAction(ParsedResult result) {\r
248     ParsedResultType type = result.getType();\r
249     if (type.equals(ParsedResultType.URI)) {\r
250       String uri = ((URIParsedResult) result).getURI();\r
251       showOpenURL("Open Web Page?", uri, uri);\r
252     } else if (type.equals(ParsedResultType.EMAIL_ADDRESS)) {\r
253       EmailAddressParsedResult emailResult = (EmailAddressParsedResult) result;\r
254       showOpenURL("Compose E-mail?", emailResult.getEmailAddress(), emailResult.getMailtoURI());\r
255     } else if (type.equals(ParsedResultType.SMS)) {\r
256       SMSParsedResult smsResult = (SMSParsedResult) result;\r
257       showOpenURL("Compose SMS?", smsResult.getNumbers()[0], smsResult.getSMSURI());\r
258     } else if (type.equals(ParsedResultType.PRODUCT)) {\r
259       ProductParsedResult productResult = (ProductParsedResult) result;\r
260       String uri = "http://www.google.com/m/products?q=" +\r
261           productResult.getNormalizedProductID() + "&source=zxing";\r
262       showOpenURL("Look Up Barcode Online?", productResult.getProductID(), uri);\r
263     } else if (type.equals(ParsedResultType.TEL)) {\r
264       TelParsedResult telResult = (TelParsedResult) result;\r
265       showOpenURL("Dial Number?", telResult.getNumber(), telResult.getTelURI());\r
266     } else {\r
267       showAlert("Barcode Detected", result.getDisplayResult());\r
268     }\r
269   }\r
270 \r
271   void itemRequest() {\r
272     ParsedResult result = (ParsedResult) resultHistory.elementAt(history.getSelectedIndex());\r
273     barcodeAction(result);\r
274   }\r
275 \r
276   void handleDecodedText(Result theResult) {\r
277     ParsedResult result = ResultParser.parseResult(theResult);\r
278     String resultString = result.toString();\r
279     int i = 0;\r
280     while (i < resultHistory.size()) {\r
281       if (resultString.equals(resultHistory.elementAt(i).toString())) {\r
282         break;\r
283       }\r
284       i++;\r
285     }\r
286     if (i == resultHistory.size()) {\r
287       resultHistory.addElement(result);\r
288       history.append(result.getDisplayResult(), null);\r
289     }\r
290     barcodeAction(result);\r
291   }\r
292 \r
293 }\r