Content Handler - Handling text, image and audio content

This section provides the source codes for the TextHandler example.

TextHandler

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);
		}
	}
}

TextViewer

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);
		}
		
	}
	
}

ChoiceBean

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;
	}
}

ChoiceList

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();
	}
}

AudioHandler

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;
    }
	
}