/* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.zxing.client.j2me; import com.google.zxing.Result; import com.google.zxing.client.result.EmailAddressParsedResult; import com.google.zxing.client.result.ParsedResult; import com.google.zxing.client.result.ParsedResultType; import com.google.zxing.client.result.ResultParser; import com.google.zxing.client.result.SMSParsedResult; import com.google.zxing.client.result.TelParsedResult; import com.google.zxing.client.result.ProductParsedResult; import com.google.zxing.client.result.URIParsedResult; import javax.microedition.lcdui.Image; import javax.microedition.io.ConnectionNotFoundException; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.media.Manager; import javax.microedition.media.MediaException; import javax.microedition.media.Player; import javax.microedition.media.control.VideoControl; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; import java.io.IOException; import java.util.Vector; /** * <p>The actual reader application {@link MIDlet}.</p> * * @author Sean Owen * @author Simon Flannery */ public final class ZXingMIDlet extends MIDlet { private static final int ALERT_TIMEOUT_MS = 5 * 1000; private Canvas canvas; private Player player; private VideoControl videoControl; private Alert confirmation; private Alert alert; private Menu history; private Vector resultHistory; Displayable getCanvas() { return canvas; } Player getPlayer() { return player; } VideoControl getVideoControl() { return videoControl; } static MultimediaManager buildMultimediaManager() { return new AdvancedMultimediaManager(); // Comment line above / uncomment below to make the basic version // return new DefaultMultimediaManager(); } protected void startApp() throws MIDletStateChangeException { try { Image image = Image.createImage("/res/zxing-icon.png"); Displayable splash = new SplashThread(this, 2000, image); Display.getDisplay(this).setCurrent(splash); resultHistory = new Vector(5); history = new Menu(this, "Scan History", "Use"); player = createPlayer(); player.realize(); MultimediaManager multimediaManager = buildMultimediaManager(); multimediaManager.setZoom(player); multimediaManager.setExposure(player); multimediaManager.setFlash(player); videoControl = (VideoControl) player.getControl("VideoControl"); canvas = new VideoCanvas(this); canvas.setFullScreenMode(true); videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas); videoControl.setDisplayLocation(0, 0); videoControl.setDisplaySize(canvas.getWidth(), canvas.getHeight()); } catch (IOException ioe) { throw new MIDletStateChangeException(ioe.toString()); } catch (MediaException me) { throw new MIDletStateChangeException(me.toString()); } // Set up one confirmation and alert object to re-use confirmation = new Alert(null); confirmation.setType(AlertType.CONFIRMATION); confirmation.setTimeout(ALERT_TIMEOUT_MS); Command yes = new Command("Yes", Command.OK, 1); confirmation.addCommand(yes); Command no = new Command("No", Command.CANCEL, 1); confirmation.addCommand(no); alert = new Alert(null); alert.setTimeout(ALERT_TIMEOUT_MS); } void splashDone() { try { videoControl.setVisible(true); player.start(); } catch (MediaException me) { showError(me); } Display.getDisplay(this).setCurrent(canvas); } private static Player createPlayer() throws IOException, MediaException { // Try a workaround for Nokias, which want to use capture://image in some cases Player player = null; String platform = System.getProperty("microedition.platform"); if (platform != null && platform.indexOf("Nokia") >= 0) { try { player = Manager.createPlayer("capture://image"); } catch (MediaException me) { // if this fails, just continue with capture://video } catch (NullPointerException npe) { // Thanks webblaz... for this improvement: // The Nokia 2630 throws this if image/video capture is not supported // We should still try to continue } catch (Error e) { // Ugly, but, it seems the Nokia N70 throws "java.lang.Error: 136" here // We should still try to continue } } if (player == null) { try { player = Manager.createPlayer("capture://video"); } catch (NullPointerException npe) { // The Nokia 2630 throws this if image/video capture is not supported throw new MediaException("Image/video capture not supported on this phone"); } } return player; } protected void pauseApp() { if (player != null) { try { player.stop(); } catch (MediaException me) { // continue? showError(me); } } } protected void destroyApp(boolean unconditional) { if (player != null) { videoControl = null; try { player.stop(); } catch (MediaException me) { // continue } player.deallocate(); player.close(); player = null; } } void stop() { destroyApp(false); notifyDestroyed(); } void historyRequest() { Display.getDisplay(this).setCurrent(history); } // Convenience methods to show dialogs private void showOpenURL(String title, String display, final String uri) { confirmation.setTitle(title); confirmation.setString(display); CommandListener listener = new CommandListener() { public void commandAction(Command command, Displayable displayable) { if (command.getCommandType() == Command.OK) { try { platformRequest(uri); } catch (ConnectionNotFoundException cnfe) { showError(cnfe); } finally { stop(); } } else { // cancel Display.getDisplay(ZXingMIDlet.this).setCurrent(getCanvas()); } } }; confirmation.setCommandListener(listener); showAlert(confirmation); } private void showAlert(String title, String text) { alert.setTitle(title); alert.setString(text); alert.setType(AlertType.INFO); showAlert(alert); } void showError(Throwable t) { String message = t.getMessage(); if (message != null && message.length() > 0) { showError(message); } else { showError(t.toString()); } } void showError(String message) { alert.setTitle("Error"); alert.setString(message); alert.setType(AlertType.ERROR); showAlert(alert); } private void showAlert(Alert alert) { Display display = Display.getDisplay(this); display.setCurrent(alert, canvas); } void barcodeAction(ParsedResult result) { ParsedResultType type = result.getType(); if (type.equals(ParsedResultType.URI)) { String uri = ((URIParsedResult) result).getURI(); showOpenURL("Open Web Page?", uri, uri); } else if (type.equals(ParsedResultType.EMAIL_ADDRESS)) { EmailAddressParsedResult emailResult = (EmailAddressParsedResult) result; showOpenURL("Compose E-mail?", emailResult.getEmailAddress(), emailResult.getMailtoURI()); } else if (type.equals(ParsedResultType.SMS)) { SMSParsedResult smsResult = (SMSParsedResult) result; showOpenURL("Compose SMS?", smsResult.getNumbers()[0], smsResult.getSMSURI()); } else if (type.equals(ParsedResultType.PRODUCT)) { ProductParsedResult productResult = (ProductParsedResult) result; String uri = "http://www.google.com/m/products?q=" + productResult.getNormalizedProductID() + "&source=zxing"; showOpenURL("Look Up Barcode Online?", productResult.getProductID(), uri); } else if (type.equals(ParsedResultType.TEL)) { TelParsedResult telResult = (TelParsedResult) result; showOpenURL("Dial Number?", telResult.getNumber(), telResult.getTelURI()); } else { showAlert("Barcode Detected", result.getDisplayResult()); } } void itemRequest() { ParsedResult result = (ParsedResult) resultHistory.elementAt(history.getSelectedIndex()); barcodeAction(result); } void handleDecodedText(Result theResult) { ParsedResult result = ResultParser.parseResult(theResult); String resultString = result.toString(); int i = 0; while (i < resultHistory.size()) { if (resultString.equals(resultHistory.elementAt(i).toString())) { break; } i++; } if (i == resultHistory.size()) { resultHistory.addElement(result); history.append(result.getDisplayResult(), null); } barcodeAction(result); } }