9fc09a91cb7053d68d4ec42fb31cc4e08669c25c
[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       videoControl = (VideoControl) player.getControl("VideoControl");\r
98       canvas = new VideoCanvas(this);\r
99       canvas.setFullScreenMode(true);\r
100       videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas);\r
101       videoControl.setDisplayLocation(0, 0);\r
102       videoControl.setDisplaySize(canvas.getWidth(), canvas.getHeight());\r
103     } catch (IOException ioe) {\r
104       throw new MIDletStateChangeException(ioe.toString());\r
105     } catch (MediaException me) {\r
106       throw new MIDletStateChangeException(me.toString());\r
107     }\r
108 \r
109     // Set up one confirmation and alert object to re-use\r
110     confirmation = new Alert(null);\r
111     confirmation.setType(AlertType.CONFIRMATION);\r
112     confirmation.setTimeout(ALERT_TIMEOUT_MS);\r
113     Command yes = new Command("Yes", Command.OK, 1);\r
114     confirmation.addCommand(yes);\r
115     Command no = new Command("No", Command.CANCEL, 1);\r
116     confirmation.addCommand(no);\r
117     alert = new Alert(null);\r
118     alert.setTimeout(ALERT_TIMEOUT_MS);\r
119   }\r
120 \r
121   void splashDone() {\r
122     try {\r
123       videoControl.setVisible(true);\r
124       player.start();\r
125     } catch (MediaException me) {\r
126       showError(me);\r
127     }\r
128     Display.getDisplay(this).setCurrent(canvas);\r
129   }\r
130 \r
131   private static Player createPlayer() throws IOException, MediaException {\r
132     // Try a workaround for Nokias, which want to use capture://image in some cases\r
133     Player player = null;\r
134     String platform = System.getProperty("microedition.platform");\r
135     if (platform != null && platform.indexOf("Nokia") >= 0) {\r
136       try {\r
137         player = Manager.createPlayer("capture://image");\r
138       } catch (MediaException me) {\r
139         // if this fails, just continue with capture://video\r
140       } catch (Error e) {\r
141         // Ugly, but, it seems the Nokia N70 throws "java.lang.Error: 136" here\r
142         // We should still try to continue\r
143       }\r
144     }\r
145     if (player == null) {\r
146       player = Manager.createPlayer("capture://video");\r
147     }\r
148     return player;\r
149   }\r
150 \r
151   protected void pauseApp() {\r
152     if (player != null) {\r
153       try {\r
154         player.stop();\r
155       } catch (MediaException me) {\r
156         // continue?\r
157         showError(me);\r
158       }\r
159     }\r
160   }\r
161 \r
162   protected void destroyApp(boolean unconditional) {\r
163     if (player != null) {\r
164       videoControl = null;\r
165       try {\r
166         player.stop();\r
167       } catch (MediaException me) {\r
168         // continue\r
169       }\r
170       player.deallocate();\r
171       player.close();\r
172       player = null;\r
173     }\r
174   }\r
175 \r
176   void stop() {\r
177     destroyApp(false);\r
178     notifyDestroyed();\r
179   }\r
180 \r
181   void historyRequest() {\r
182     Display.getDisplay(this).setCurrent(history);\r
183   }\r
184 \r
185   // Convenience methods to show dialogs\r
186 \r
187   private void showOpenURL(String title, String display, final String uri) {\r
188     confirmation.setTitle(title);\r
189     confirmation.setString(display);\r
190     CommandListener listener = new CommandListener() {\r
191       public void commandAction(Command command, Displayable displayable) {\r
192         if (command.getCommandType() == Command.OK) {\r
193           try {\r
194             platformRequest(uri);\r
195           } catch (ConnectionNotFoundException cnfe) {\r
196             showError(cnfe);\r
197           } finally {\r
198             stop();\r
199           }\r
200         } else {\r
201           // cancel\r
202           Display.getDisplay(ZXingMIDlet.this).setCurrent(getCanvas());\r
203         }\r
204       }\r
205     };\r
206     confirmation.setCommandListener(listener);\r
207     showAlert(confirmation);\r
208   }\r
209 \r
210   private void showAlert(String title, String text) {\r
211     alert.setTitle(title);\r
212     alert.setString(text);\r
213     alert.setType(AlertType.INFO);\r
214     showAlert(alert);\r
215   }\r
216 \r
217   void showError(Throwable t) {\r
218     String message = t.getMessage();\r
219     if (message != null && message.length() > 0) {\r
220       showError(message);\r
221     } else {\r
222       showError(t.toString());\r
223     }\r
224   }\r
225 \r
226   void showError(String message) {\r
227     alert.setTitle("Error");\r
228     alert.setString(message);\r
229     alert.setType(AlertType.ERROR);\r
230     showAlert(alert);\r
231   }\r
232 \r
233   private void showAlert(Alert alert) {\r
234     Display display = Display.getDisplay(this);\r
235     display.setCurrent(alert, canvas);\r
236   }\r
237 \r
238   void barcodeAction(ParsedResult result) {\r
239     ParsedResultType type = result.getType();\r
240     if (type.equals(ParsedResultType.URI)) {\r
241       String uri = ((URIParsedResult) result).getURI();\r
242       showOpenURL("Open Web Page?", uri, uri);\r
243     } else if (type.equals(ParsedResultType.EMAIL_ADDRESS)) {\r
244       EmailAddressParsedResult emailResult = (EmailAddressParsedResult) result;\r
245       showOpenURL("Compose E-mail?", emailResult.getEmailAddress(), emailResult.getMailtoURI());\r
246     } else if (type.equals(ParsedResultType.SMS)) {\r
247       SMSParsedResult smsResult = (SMSParsedResult) result;\r
248       showOpenURL("Compose SMS?", smsResult.getNumber(), smsResult.getSMSURI());\r
249     } else if (type.equals(ParsedResultType.PRODUCT)) {\r
250       ProductParsedResult productResult = (ProductParsedResult) result;\r
251       String uri = "http://www.upcdatabase.com/item.asp?upc=" + productResult.getNormalizedProductID();\r
252       showOpenURL("Look Up Barcode Online?", productResult.getProductID(), uri);\r
253     } else if (type.equals(ParsedResultType.TEL)) {\r
254       TelParsedResult telResult = (TelParsedResult) result;\r
255       showOpenURL("Dial Number?", telResult.getNumber(), telResult.getTelURI());\r
256     } else {\r
257       showAlert("Barcode Detected", result.getDisplayResult());\r
258     }\r
259   }\r
260 \r
261   void itemRequest() {\r
262     ParsedResult result = (ParsedResult) resultHistory.elementAt(history.getSelectedIndex());\r
263     barcodeAction(result);\r
264   }\r
265 \r
266   void handleDecodedText(Result theResult) {\r
267     ParsedResult result = ResultParser.parseResult(theResult);\r
268     String resultString = result.toString();\r
269     int i = 0;\r
270     while (i < resultHistory.size()) {\r
271       if (resultString.equals(resultHistory.elementAt(i).toString())) {\r
272         break;\r
273       }\r
274       i++;\r
275     }\r
276     if (i == resultHistory.size()) {\r
277       resultHistory.addElement(result);\r
278       history.append(result.getDisplayResult(), null);\r
279     }\r
280     barcodeAction(result);\r
281   }\r
282 \r
283 }\r