This section provides the source codes for the TextHandler example.
package com.nokia.midp.example.jsr211.texthandler; import javax.microedition.content.ContentHandlerServer; import javax.microedition.content.Invocation; import javax.microedition.content.Registry; import javax.microedition.content.RequestListener; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; public class TextHandler extends MIDlet implements CommandListener, RequestListener { /**Confirmation screen title*/ private static final String CONFIRM = "Confirmation"; /**Choice list title*/ private static final String FAVORITE_LINKS = "Favorite Links"; /** content type constant*/ private static final String CONTENT_TYPE = "text/plain"; /** Current class name*/ private static final String CLASS_NAME = "com.nokia.midp.example.jsr211.texthandler.TextHandler"; /** Display instance*/ Display display = null; /** Proceed the invocation confirmation*/ private Command proceedCommand = new Command("Proceed", Command.OK, 1); /** Go back to the choice list window*/ private Command backCommand = new Command("Back", Command.OK, 2); /** Exit the application and go back to the invoker*/ private Command exitCommand = new Command("Exit", Command.BACK, 2); /** Current invocation, null if no Invocation. */ private Invocation invocation; /** ContentHandlerServer from which to get requests. */ private ContentHandlerServer handler; /** Access to Registry functions and responses. */ private Registry registry; /**instance to display choice list*/ ChoiceList choices; /**Invocation URL*/ String url; /** * Constructor creates Display instance and create choice list. */ public TextHandler() { display = Display.getDisplay(this); //Display the choice list choices = new ChoiceList(FAVORITE_LINKS, this); display.setCurrent(choices); } protected void startApp() throws MIDletStateChangeException { } protected void destroyApp(boolean arg0) { } protected void pauseApp() { } /** * Method displays Text Invocation. Current invocation handles * Text Content type "text/plain" * @param invoc invocation with content type "text/plain" */ void showCurrentInvocation(Invocation invoc) { Form textViewerFrom = new TextViewer(invoc, this); display.setCurrent(textViewerFrom); } /** * It does handler registration. Also needs user input to process further. * @param _url invocation url */ void registerAndConfirm(String _url) { url = _url; try { registry = Registry.getRegistry(TextHandler.CLASS_NAME); handler = registry.register(TextHandler.CLASS_NAME, new String[] { TextHandler.CONTENT_TYPE }, null, null, null, null, null); if (handler != null) { handler.setListener(this); } } catch (Exception che) { che.printStackTrace(); } if (registry != null && handler != null) { confirmationScree("Registration Successful!\n\nWant to Proceed?"); } } /** * It displays alert messages * @param message Message to display **/ private void displayMessage(String message) { Alert alert = new Alert("Message", message, null, AlertType.INFO); display.setCurrent(alert); } /** * Confirmation screen to process further. * @param msg Message to display on confirmation screen * */ private void confirmationScree(String msg) { Form confirmForm = new Form(CONFIRM); confirmForm.addCommand(backCommand); confirmForm.addCommand(proceedCommand); confirmForm.append(msg); confirmForm.setCommandListener(this); display.setCurrent(confirmForm); } /** * Handle Invocation commands */ public void commandAction(Command command, Displayable disp) { if (command == proceedCommand) { doInvoke(url); } else if (command == backCommand) { display.setCurrent(choices); } else if (command == exitCommand) { destroyApp(true); notifyDestroyed(); } } /** * Handles incoming invocation request using the ContentHandlerServer * instance. If there is a current Invocation finish it so the next * Contact can be displayed. */ public void invocationRequestNotify(ContentHandlerServer server) { if (invocation != null) { handler.finish(invocation, Invocation.OK); } invocation = handler.getRequest(false); if (invocation != null) { showCurrentInvocation(invocation); } } /** * Finish the current invocation * @param invocStatus */ void doFinish(int invocStatus) { if (invocStatus == Invocation.OK) { if (invocation != null) invocation = null; destroyApp(true); notifyDestroyed(); } } /** * Invoke the URL provided. * @param url http URL */ void doInvoke(String url) { try { Invocation invoc = new Invocation(url); if (registry.invoke(invoc)) { destroyApp(true); notifyDestroyed(); } else { } } catch (Exception ex) { displayMessage("Could not link to " + url); } } }
package com.nokia.midp.example.jsr211.texthandler; import java.io.InputStream; import javax.microedition.content.Invocation; import javax.microedition.io.HttpConnection; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.lcdui.Item; import javax.microedition.lcdui.StringItem; /** * Class display the text invocation. It uses a form to display the invocation text. * Basically, it makes HTTP Connection with the invocation URL and get the content. * @author gothadiy * */ public class TextViewer extends Form implements CommandListener{ /** Intial title of the text display form*/ private static final String DEFAULT_TITLE = "Text Viewer"; /** Message saying.. No content to display*/ private static final String NO_CONTENT = "no content to display"; /** Instance of TextHandler used to display form*/ private TextHandler textHandler = null; /** Instance of invocation. Get value from the constructor*/ private Invocation invoc = null; Command detailCommand = new Command("Details",Command.OK,1); /** Go back to the choice list window*/ Command backCommand = new Command("Back", Command.OK, 2); /** * Constructor initialize gives instances of TextHandler * and Invocation and initalize the text contents. * * @param _invoc Text Invocation instance. * @param _textHandler Instance of TextHandler */ TextViewer(Invocation _invoc, TextHandler _textHandler){ super(TextViewer.DEFAULT_TITLE); invoc = _invoc; textHandler = _textHandler; this.addCommand(detailCommand); this.addCommand(backCommand); setCommandListener(this); displayContent(invoc); } /** * It validates the invoc object and URL. * It creates the HTTP connection and get the text content. Append it to the form and display. * * @param invoc Text Invocation instance. */ private void displayContent(Invocation invoc) { String url = null; if ((invoc == null)) { this.append(TextViewer.NO_CONTENT); return; } if ((url = invoc.getURL()) == null){ this.append(TextViewer.NO_CONTENT); return; } // Set file name as a form title String title = url.substring(url.lastIndexOf('/')+1); this.setTitle(TextViewer.DEFAULT_TITLE+" - "+title); HttpConnection conn = null; InputStream input = null; StringBuffer txtContentBuff; try { //Open connection using invocation conn = (HttpConnection)invoc.open(false); conn.setRequestMethod(HttpConnection.GET); // If not successful, Display response code with response message. if (conn.getResponseCode() != HttpConnection.HTTP_OK) { this.append(conn.getResponseMessage() + " (" + conn.getResponseCode() + ")"); return; } // Create StringBuffer with the size of response length txtContentBuff = new StringBuffer((int)conn.getLength()); // Max size supported is char 4096; int maxLen = 4096; input = conn.openInputStream(); // Read char and store it to the StringBuffer int ch = 0; while ((ch = input.read()) != -1) { txtContentBuff.append((char)ch); if (txtContentBuff.length() >= maxLen) { break; } } // Process the buffer and append text to the form this.append(new StringItem(null, txtContentBuff.toString(), Item.PLAIN)); } catch (Throwable th) { txtContentBuff = null; th.printStackTrace(); } finally { try { if (input != null) { input.close(); } if (conn != null) { conn.close(); } } catch (Exception e) {} } } public void commandAction(Command command, Displayable disp) { if (command == detailCommand){ try { String details = ""; details = "Invocation Type: "+invoc.findType()+ "\n"; details += "Action: "+invoc.getAction()+ "\n"; details += "ID: "+invoc.getID()+ "\n"; details += "Invoking App Name: "+invoc.getInvokingAppName()+ "\n"; details += "Invoking Authority: "+invoc.getInvokingAuthority()+ "\n"; details += "Invoking ID: "+ invoc.getInvokingID() +"\n"; Alert alert = new Alert("Details",details,null,AlertType.INFO); alert.setTimeout(Alert.FOREVER); textHandler.display.setCurrent(alert); } catch (Exception e) { e.printStackTrace(); } } else if (command == backCommand) { textHandler.doFinish(Invocation.OK); textHandler.display.setCurrent(textHandler.choices); } } }
package com.nokia.midp.example.jsr211.texthandler; import javax.microedition.lcdui.StringItem; /** * Purely a bean class, used to manage favorite choice list. * */ public class ChoiceBean { /** Choice Key also used as a choice title*/ private StringItem keyTitle; /** Contains item URL*/ private String choiceName; ChoiceBean(StringItem _keyTitle, String _choiceName){ keyTitle = _keyTitle; choiceName =_choiceName; } public StringItem getKeyTitle() { return keyTitle; } public void setKeyTitle(StringItem keyTitle) { this.keyTitle = keyTitle; } public String getChoiceName() { return choiceName; } public void setChoiceName(String choiceName) { this.choiceName = choiceName; } }
package com.nokia.midp.example.jsr211.texthandler; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Vector; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.lcdui.Item; import javax.microedition.lcdui.ItemCommandListener; import javax.microedition.lcdui.StringItem; import javax.microedition.lcdui.TextField; /** * * Class provides basic methods to add/delete items from the list and give the item URL. * */ public class ChoiceList extends Form implements CommandListener, ItemCommandListener { /** Message saying.. fail to load text invocation. */ private static final String MSG_FAILED_TO_LOAD_TEXT = "Failed to load text"; /** Message saying.. Invalid file*/ private static final String MSG_INVALID_FILE = "Invalid file"; /** URL Choice from JAD*/ private static final String JAD_NOKIA_CHOICE = "Nok-Choice-"; /** Resource file name from JAD*/ private static final String JAD_NOKIA_RESOURCE_FILE = "Nok-Resource-File-Name"; /** New line separator*/ private static final String NEW_LINE = "\r\n"; /** Key value separator for link.txt file. */ private static final String SEPARATOR = "~"; /** Display instance. */ private Display display = null; /** List of choices */ private Vector choiceList = new Vector(); /** Alert to display choice details*/ Alert alert = new Alert("Choice Details"); /** TextField to enter Title of the choice */ private TextField titleTextField; /** TextField to enter choice URL. */ private TextField urlTextField; /** Command to execute the choice */ private Command fireCommand = new Command("Execute", Command.ITEM, 1); /** Command to add item to the list. */ private Command addCommand = new Command("Add", Command.ITEM, 2); /** Command to Delete Choice from the list. */ private Command deleteCommand = new Command("Delete", Command.ITEM, 3); /** Command to view details of the choice */ private Command detailCommand = new Command("Details", Command.ITEM, 4); /** Command to save item to the list. */ private Command saveCommand = new Command("Save", Command.ITEM, 1); /** Command to exit from the application */ private Command exitCommand = new Command("Exit", Command.ITEM, 5); /** Command to exit from the application */ private Command backCommand = new Command("Back", Command.BACK, 6); /** The ItemCommandListener that gets notified of select events. */ private TextHandler textHandler; //ContentInvoker invoker = null; /** * Constructor to handle list of Choices * * @param title Choice list title. * @param _textHandler Instance of TextHandler class to handle UI part. */ public ChoiceList(String title, TextHandler _textHandler) { super(title); textHandler = _textHandler; display = _textHandler.display; // Read favorites links form the resource file String strChoices = null; try { strChoices = readResourceFile(); } catch (IOException ex) { choiceList.removeAllElements(); choiceList.addElement(ChoiceList.MSG_INVALID_FILE); } try { generateChoiceList(strChoices); } catch (Exception e) { // Failed to load resources choiceList.removeAllElements(); choiceList.addElement(ChoiceList.MSG_FAILED_TO_LOAD_TEXT); } displayChoices(); configureTextFields(); } /** * TextField configuration */ private void configureTextFields() { titleTextField = new TextField("Add Title:", "", 30, TextField.INITIAL_CAPS_WORD); titleTextField.setLayout(Item.LAYOUT_DEFAULT | Item.LAYOUT_NEWLINE_AFTER); titleTextField.addCommand(saveCommand); titleTextField.setItemCommandListener(this); urlTextField = new TextField("Add Link:", "http://", 128, TextField.URL); urlTextField.setLayout(Item.LAYOUT_DEFAULT | Item.LAYOUT_NEWLINE_AFTER); urlTextField.addCommand(saveCommand); urlTextField.setItemCommandListener(this); } /** * Display favorite choice list */ private void displayChoices() { for (int index = 0; index < choiceList.size(); index++) { ChoiceBean choiceBean = (ChoiceBean) choiceList.elementAt(index); this.append(choiceBean.getKeyTitle()); } addCommand(exitCommand); setCommandListener(this); } /** * Create choice list based resource string. * Method reads choices from two files. */ private void generateChoiceList(String strChoices) { while ((strChoices != null) && (strChoices.indexOf(ChoiceList.NEW_LINE) != -1)) { String item = strChoices.substring(0, strChoices .indexOf(ChoiceList.NEW_LINE)); String key = item.substring(0, item.indexOf(ChoiceList.SEPARATOR)); String value = item .substring(item.indexOf(ChoiceList.SEPARATOR) + 1); StringItem choice = new StringItem(null, key, Item.HYPERLINK); choice.setLayout(Item.LAYOUT_2 | Item.LAYOUT_NEWLINE_AFTER); choice.setDefaultCommand(fireCommand); //choice.addCommand(backCommand); choice.addCommand(addCommand); choice.addCommand(deleteCommand); choice.addCommand(detailCommand); choice.setItemCommandListener(this); ChoiceBean choiceBean = new ChoiceBean(choice, value); choiceList.addElement(choiceBean); strChoices = strChoices.substring(strChoices .indexOf(ChoiceList.NEW_LINE) + 2); } // Read from jad file, if entry exists int keyNum = 1; strChoices = null; do { strChoices = textHandler.getAppProperty(ChoiceList.JAD_NOKIA_CHOICE + keyNum++); System.out.println(strChoices); if (strChoices == null) return; String key = ""; String value = ""; if (strChoices.indexOf(ChoiceList.SEPARATOR) != -1) { key = strChoices.substring(0, strChoices .indexOf(ChoiceList.SEPARATOR)); value = strChoices.substring(strChoices .indexOf(ChoiceList.SEPARATOR) + 1); if (value != null) { StringItem choice = new StringItem(null, key, Item.HYPERLINK); choice.setLayout(Item.LAYOUT_2 | Item.LAYOUT_NEWLINE_AFTER); choice.setDefaultCommand(fireCommand); choice.addCommand(addCommand); choice.addCommand(deleteCommand); choice.addCommand(detailCommand); choice.setItemCommandListener(this); ChoiceBean choiceBean = new ChoiceBean(choice, value); choiceList.addElement(choiceBean); } } } while (strChoices != null); } /** * Read data from the resource file and generate String. * @return string generated after reading the data from the resource file * @throws IOException */ private String readResourceFile() throws IOException { InputStream is = getClass().getResourceAsStream( textHandler.getAppProperty(JAD_NOKIA_RESOURCE_FILE)); InputStreamReader r = new InputStreamReader(is); char[] buffer = new char[32]; StringBuffer sb = new StringBuffer(); int count; while ((count = r.read(buffer, 0, buffer.length)) > -1) { sb.append(buffer, 0, count); } return sb.toString(); } /** * Add Choice to the current list. * @param keyTitle title of the new choice * @param choiceName URL of the given choice */ public void addChoice(String keyTitle, String choiceName) { StringItem choice = new StringItem(null, keyTitle, Item.HYPERLINK); choice.setLayout(Item.LAYOUT_2 | Item.LAYOUT_NEWLINE_AFTER); choice.setDefaultCommand(fireCommand); choice.addCommand(addCommand); choice.addCommand(addCommand); choice.addCommand(deleteCommand); choice.addCommand(detailCommand); choice.setItemCommandListener(this); ChoiceBean choiceBean = new ChoiceBean(choice, choiceName); choiceList.addElement(choiceBean); } /** * Delete choice from the current list * * @param index delete choice based on the given index. */ public void deleteChoice(int index) { choiceList.removeElementAt(index); } /** * Handles item specific command */ public void commandAction(Command command, Item item) { int itemIndex = getItemIndex(item); if (command == fireCommand) { if (textHandler != null) { String url = textHandler.choices.getURL(item); if (url == null) { url = ((StringItem) item).getText(); } textHandler.registerAndConfirm(url); } } else if (command == addCommand) { // Delete entire list from the form. removeItems(); // Reset strings titleTextField.setString(""); urlTextField.setString("http://"); // Add text fields to add new choice this.insert(0, titleTextField); this.insert(1, urlTextField); } else if (command == deleteCommand) { this.delete(itemIndex); choiceList.removeElementAt(itemIndex); } else if (command == detailCommand) { alert.setString(((ChoiceBean) choiceList.elementAt(itemIndex)) .getChoiceName()); alert.setTimeout(Alert.FOREVER); alert.setType(AlertType.INFO); display.setCurrent(alert); } else if (command == saveCommand) { addChoice(titleTextField.getString().trim(), urlTextField .getString().trim()); // Delete entire list from the form. removeItems(); displayChoices(); } } Command yes = new Command("Yes", Command.OK, 1); Command no = new Command("No", Command.CANCEL, 2); void displayMessage(String msg) { Form form = new Form("Text Viewer"); form.append(msg); form.addCommand(yes); form.addCommand(no); form.setCommandListener(this); display.setCurrent(form); } private void removeItems() { while (this.size() > 0) { this.delete(0); } } public void commandAction(Command command, Displayable disp) { if (command == exitCommand) { textHandler.destroyApp(true); textHandler.notifyDestroyed(); } } /** * Find the index of the item in the form. * @param item to find the index of * @return the index of the item or -1 if not found. */ private int getItemIndex(Item item) { int itemIndex = 0; for (itemIndex = 0; itemIndex < this.size(); itemIndex++) { if (this.get(itemIndex) == item) { return itemIndex; } } return -1; } /** * Get the url associated with the item. * @param item for which to get the URL * @return the URL at index */ public String getURL(Item item) { int index = getItemIndex(item); return (index < 0) ? null : ((ChoiceBean) choiceList.elementAt(index)) .getChoiceName(); } }
package com.nokia.midp.example.jsr211.audiohandler; import java.io.IOException; import java.io.InputStream; import javax.microedition.content.ContentHandlerServer; import javax.microedition.content.Invocation; import javax.microedition.content.Registry; import javax.microedition.content.RequestListener; import javax.microedition.io.HttpConnection; import javax.microedition.lcdui.Alert; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Form; import javax.microedition.lcdui.Image; import javax.microedition.lcdui.ImageItem; import javax.microedition.lcdui.Item; import javax.microedition.lcdui.Ticker; import javax.microedition.media.Manager; import javax.microedition.media.Player; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; /** * * Class has functionality how to fetch content from the server and play it using Player. * RequestListenr will work to notify incoming invocation. It will start new thread to handle it. * */ public class AudioHandler extends MIDlet implements CommandListener, RequestListener { /** Audio Player Form Title*/ private static final String FORM_TITLE = "Audio Player"; /** Audio Player ticker title*/ private static final String TICKER_TITLE = "Playing Audio File"; /** Message constant*/ private static final String MSG_CAN_NOT_READ_AUDIO = "Can not read Audio"; /** Audio content type constant*/ private static final String CONTENT_TYPE_AUDIO = "audio/x-wav"; /** Current class name*/ private static final String CLASS_NAME = "com.nokia.midp.example.jsr211.audiohandler.AudioHandler"; /** Display instance*/ private Display display = null; /** Form to display audio UI*/ private Form audioForm = null; /** Stop audio playing*/ private Command stopCommand = new Command("Back",Command.OK,1); /** Exit the application and go back to the invoker*/ private Command exitCommand = new Command("Exit", Command.BACK,1); /** Instance of the player*/ private Player player; /** Current invocation, null if no Invocation. */ private Invocation invocation; /** ContentHandlerServer from which to get requests. */ private ContentHandlerServer handler; /** Access to Registry functions and responses. */ private Registry registry; /** Audio Input Stream stores audio data comes from the server. */ private InputStream audioStream; /** Stores the type of the Invocation content. */ private String reveivedType; /** * Constructor initializes the display instance as well as create the instace of * ContentHandlerServer using Registry class. It also sets the RequestLister for * any incoming Invocation. */ public AudioHandler() { display = Display.getDisplay(this); try { registry = Registry.getRegistry(AudioHandler.CLASS_NAME); handler = registry.register(AudioHandler.CLASS_NAME, new String[] { AudioHandler.CONTENT_TYPE_AUDIO }, null, null, null, null, null); if (handler != null) { handler.setListener(this); } } catch (Exception che) { che.printStackTrace(); } } /** * It displays audioForm and removes extra commands and items. */ private void displayaAudioPlayForm() { // Remove previous items and command audioForm = new Form(AudioHandler.FORM_TITLE); audioForm.removeCommand(exitCommand); String name = invocation.getURL(); name = name.substring(name.lastIndexOf('/')+1); audioForm.addCommand(stopCommand); audioForm.setCommandListener(this); audioForm.setTicker(new Ticker(AudioHandler.TICKER_TITLE)); try{ ImageItem imageItem = new ImageItem(null, null, Item.LAYOUT_CENTER, "-no image-"); imageItem.setImage(Image.createImage("/com/nokia/midp/example/jsr211/res/audio_player.png")); audioForm.append(imageItem); }catch(Exception e){ } display.setCurrent(audioForm); } protected void startApp() throws MIDletStateChangeException { } protected void destroyApp(boolean arg0) throws MIDletStateChangeException { } protected void pauseApp() { } /** * Handlers Audio commands * * playCommand Start playing audio. * Invoke the URL in a new Thread to prevent blocking the user interface. * * stopCommand Stop playing and go back to the main screen. * * exitCommand exit from the current app and go back to the invoker app * @throws MIDletStateChangeException */ public void commandAction(Command command, Displayable disp){ System.out.println(command.getLabel()); if (command.getLabel().equals("Back") || command == exitCommand){ try { doFinish(Invocation.OK); destroyApp(true); notifyDestroyed(); } catch (MIDletStateChangeException e) { e.printStackTrace(); } } } /** * Handles incoming invocation request using the ContentHandlerServer instance. * If there is a current Invocation finish it so the next Contact can be displayed. * Get the requested invocation in invoc instance and call method * handleAudio(invoc) to handle audio. */ public void invocationRequestNotify(ContentHandlerServer server) { System.out.println("invocationRequestNotify()"); if (invocation != null) { handler.finish(invocation, Invocation.OK); } invocation = handler.getRequest(false); if (invocation != null) { handleAudio(invocation); } } /** * Creates Http connection with the server and get located content in * InputStream audioIN. It starts thread to play audio. * @param _invoc */ private void handleAudio(Invocation _invoc) { HttpConnection conn = null; try { conn = (HttpConnection)_invoc.open(false); // Check the status and read the content int status = conn.getResponseCode(); if (status != HttpConnection.HTTP_OK) { Alert alert = new Alert(AudioHandler.MSG_CAN_NOT_READ_AUDIO, "Audio not available at " + _invoc.getURL(), null, AlertType.ERROR); display.setCurrent(alert); doFinish(Invocation.CANCELLED); return; } reveivedType = conn.getType(); /** * If invocation content type does not match with the app content type then * display main screen without handling the content. */ if (!reveivedType.equals(AudioHandler.CONTENT_TYPE_AUDIO)){ //inputAudioUrlFrom(); } // Get the image from the connection audioStream = conn.openInputStream(); new Thread(new Runnable() { public void run() { try{ displayaAudioPlayForm(); player = Manager.createPlayer(audioStream, AudioHandler.CONTENT_TYPE_AUDIO); player.start(); }catch(Exception e){ Alert alert = new Alert(AudioHandler.MSG_CAN_NOT_READ_AUDIO, "Unable to play Audio", null, AlertType.ERROR); display.setCurrent(alert); doFinish(Invocation.CANCELLED); } } }).start(); } catch (Exception e) { Alert alert = new Alert(AudioHandler.MSG_CAN_NOT_READ_AUDIO, "Audio not available", null, AlertType.ERROR); display.setCurrent(alert); doFinish(Invocation.CANCELLED); } finally { try { if (conn != null) { conn.close(); } } catch (IOException ioe) { } } } /**Finishes the Invocation.*/ boolean doFinish(int status) { if (invocation != null) { boolean mustExit = handler.finish(invocation, status); invocation = null; if (mustExit) { try { destroyApp(true); } catch (MIDletStateChangeException e) { e.printStackTrace(); } notifyDestroyed(); return true; } else { // Application does not need to exit } } return false; } }