AudioHandler.java

/**
 * Copyright (c) 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners.
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.contenthandler.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.example.contenthandler.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.STOP, 1);
    // Exit the application and go back to the invoker
    private Command exitCommand = new Command("Exit", Command.EXIT, 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 creates the
     * instance of ContentHandlerServer using Registry class. It also sets the
     * RequestListener 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 displayAudioPlayForm() {
        // 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("/note.png"));
            audioForm.append(imageItem);
        }
        catch (Exception e) {
            //e.printStackTrace();
        }

        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) {
        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) {

        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 {

                        displayAudioPlayForm();

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