8335a53aa369da84f6f5883379673545e4f15d87
[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 (Error e) {\r
142         // Ugly, but, it seems the Nokia N70 throws "java.lang.Error: 136" here\r
143         // We should still try to continue\r
144       }\r
145     }\r
146     if (player == null) {\r
147       player = Manager.createPlayer("capture://video");\r
148     }\r
149     return player;\r
150   }\r
151 \r
152   protected void pauseApp() {\r
153     if (player != null) {\r
154       try {\r
155         player.stop();\r
156       } catch (MediaException me) {\r
157         // continue?\r
158         showError(me);\r
159       }\r
160     }\r
161   }\r
162 \r
163   protected void destroyApp(boolean unconditional) {\r
164     if (player != null) {\r
165       videoControl = null;\r
166       try {\r
167         player.stop();\r
168       } catch (MediaException me) {\r
169         // continue\r
170       }\r
171       player.deallocate();\r
172       player.close();\r
173       player = null;\r
174     }\r
175   }\r
176 \r
177   void stop() {\r
178     destroyApp(false);\r
179     notifyDestroyed();\r
180   }\r
181 \r
182   void historyRequest() {\r
183     Display.getDisplay(this).setCurrent(history);\r
184   }\r
185 \r
186   // Convenience methods to show dialogs\r
187 \r
188   private void showOpenURL(String title, String display, final String uri) {\r
189     confirmation.setTitle(title);\r
190     confirmation.setString(display);\r
191     CommandListener listener = new CommandListener() {\r
192       public void commandAction(Command command, Displayable displayable) {\r
193         if (command.getCommandType() == Command.OK) {\r
194           try {\r
195             platformRequest(uri);\r
196           } catch (ConnectionNotFoundException cnfe) {\r
197             showError(cnfe);\r
198           } finally {\r
199             stop();\r
200           }\r
201         } else {\r
202           // cancel\r
203           Display.getDisplay(ZXingMIDlet.this).setCurrent(getCanvas());\r
204         }\r
205       }\r
206     };\r
207     confirmation.setCommandListener(listener);\r
208     showAlert(confirmation);\r
209   }\r
210 \r
211   private void showAlert(String title, String text) {\r
212     alert.setTitle(title);\r
213     alert.setString(text);\r
214     alert.setType(AlertType.INFO);\r
215     showAlert(alert);\r
216   }\r
217 \r
218   void showError(Throwable t) {\r
219     String message = t.getMessage();\r
220     if (message != null && message.length() > 0) {\r
221       showError(message);\r
222     } else {\r
223       showError(t.toString());\r
224     }\r
225   }\r
226 \r
227   void showError(String message) {\r
228     alert.setTitle("Error");\r
229     alert.setString(message);\r
230     alert.setType(AlertType.ERROR);\r
231     showAlert(alert);\r
232   }\r
233 \r
234   private void showAlert(Alert alert) {\r
235     Display display = Display.getDisplay(this);\r
236     display.setCurrent(alert, canvas);\r
237   }\r
238 \r
239   void barcodeAction(ParsedResult result) {\r
240     ParsedResultType type = result.getType();\r
241     if (type.equals(ParsedResultType.URI)) {\r
242       String uri = ((URIParsedResult) result).getURI();\r
243       showOpenURL("Open Web Page?", uri, uri);\r
244     } else if (type.equals(ParsedResultType.EMAIL_ADDRESS)) {\r
245       EmailAddressParsedResult emailResult = (EmailAddressParsedResult) result;\r
246       showOpenURL("Compose E-mail?", emailResult.getEmailAddress(), emailResult.getMailtoURI());\r
247     } else if (type.equals(ParsedResultType.SMS)) {\r
248       SMSParsedResult smsResult = (SMSParsedResult) result;\r
249       showOpenURL("Compose SMS?", smsResult.getNumber(), smsResult.getSMSURI());\r
250     } else if (type.equals(ParsedResultType.PRODUCT)) {\r
251       ProductParsedResult productResult = (ProductParsedResult) result;\r
252       String uri = "http://www.upcdatabase.com/item.asp?upc=" + productResult.getNormalizedProductID();\r
253       showOpenURL("Look Up Barcode Online?", productResult.getProductID(), uri);\r
254     } else if (type.equals(ParsedResultType.TEL)) {\r
255       TelParsedResult telResult = (TelParsedResult) result;\r
256       showOpenURL("Dial Number?", telResult.getNumber(), telResult.getTelURI());\r
257     } else {\r
258       showAlert("Barcode Detected", result.getDisplayResult());\r
259     }\r
260   }\r
261 \r
262   void itemRequest() {\r
263     ParsedResult result = (ParsedResult) resultHistory.elementAt(history.getSelectedIndex());\r
264     barcodeAction(result);\r
265   }\r
266 \r
267   void handleDecodedText(Result theResult) {\r
268     ParsedResult result = ResultParser.parseResult(theResult);\r
269     String resultString = result.toString();\r
270     int i = 0;\r
271     while (i < resultHistory.size()) {\r
272       if (resultString.equals(resultHistory.elementAt(i).toString())) {\r
273         break;\r
274       }\r
275       i++;\r
276     }\r
277     if (i == resultHistory.size()) {\r
278       resultHistory.addElement(result);\r
279       history.append(result.getDisplayResult(), null);\r
280     }\r
281     barcodeAction(result);\r
282   }\r
283 \r
284 }\r