BCExchangerMIDlet.java

/*
 * Copyright © 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.bcexchanger;

import java.util.Vector;

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import com.nokia.example.bcexchanger.comm.ExchangeListener;
import com.nokia.example.bcexchanger.comm.ExchangerComm;
import com.nokia.example.bcexchanger.comm.ExchangerCommImpl;
import com.nokia.example.bcexchanger.ui.AddressBookScreen;
import com.nokia.example.bcexchanger.ui.AlertMessage;
import com.nokia.example.bcexchanger.ui.MainScreen;
import com.nokia.example.bcexchanger.ui.ProgressScreen;
import com.nokia.example.bcexchanger.ui.Screen;
import com.nokia.example.bcexchanger.ui.ServiceListScreen;

/**
 * 
 * This is the main application class which extends MIDlet class. It
 * serves as a parent to UI states (package example.BCExchanger.ui)
 * and listens to communication events by implementing
 * ExchangeListener interface
 * 
 * @see example.BCExchanger.comm.ExchangeListener
 */
public class BCExchangerMIDlet extends MIDlet
        implements ExchangeListener {

    private boolean commIsInitialized = false;
    private ExchangerComm comm;
    private int selectedServiceIndex;
    private MainScreen scr = new MainScreen(this);

    /**
     * Constructor
     */
    public BCExchangerMIDlet() {
    }

    /**
     * Changes the current UI screen
     * <p>
     * This method is used to display and make active a UI screen
     * 
     * @param screen -
     *          UI screen to display
     * @see example.BCExchanger.ui.Screen
     */
    public void changeScreen(Screen screen) {
        screen.makeActive();
    }

    /**
     * Called to force termination of MIDlet
     */
    public void quit() {
        if (comm != null) {
            comm.cancelWaiting();
        }

        try {
            destroyApp(true);
            notifyDestroyed();
        } catch (MIDletStateChangeException e) {
            // Ignore, we are closing anyways
        }
    }

    /**
     * Saves the index of the service of choice
     * <p>
     * This method is used in case several services are found during
     * service discovery In this case the ServiceListScreen is displayed
     * and on user selection this method is called to save the index of
     * the service of choice.
     * 
     * @param index -
     *          index of the service chosen by the user
     */
    public void serviceSelected(int index) {
        selectedServiceIndex = index;
    }

    /**
     * Initializes the communication module
     */
    public void initComm() {
        if (!commIsInitialized) { // avoid double initializing
            comm = new ExchangerCommImpl(this);
            commIsInitialized = true;
        }
    }

    /**
     * Getter method for Exchanger - class representing communication
     * module
     * 
     * @return a class implementing ExchangerComm interface,
     *         representing communication module
     */
    public ExchangerComm getExchanger() {
        return comm;
    }

    protected void destroyApp(boolean arg0)
            throws MIDletStateChangeException {
    }

    protected void startApp() throws MIDletStateChangeException {
        // ensure that we have own business card selected
        String uid = null;
        try {
            uid = Storage.getBCUID();
        } catch (Exception e) {
            changeScreen(new AlertMessage(this,
                    "Cannot use the persistent storage. Application will exit"));
            return;
        }

        if (uid == null) {
            // if the MIDlet has not been started before
            // and own business card has not been chosen
            changeScreen(new AddressBookScreen(this));
        } else {
            changeScreen(scr);
        }
    }

    protected void pauseApp() {
    }

    public void onInquiryComplete(int code) {
        if (code == ExchangerComm.DONE) {
            String text = "Searching for Business Card Exchange service...";
            changeScreen(new ProgressScreen(this, text));
        } else if (code == ExchangerComm.ERROR) {
            changeScreen(new AlertMessage(this, "Errors during inquiry",
                    scr));
        } else if (code == ExchangerComm.CANCELED) {
            changeScreen(new AlertMessage(this, "Inquiry is canceled",
                    scr));
        } else {
            // Unknown error
            throw new RuntimeException("Internal error #26");
        }

    }

    public void onServiceDiscoveryComplete(int code) {
        if (code == ExchangerComm.DONE) {
            String text = "Sending own business card...";
            changeScreen(new ProgressScreen(this, text));
        } else if (code == ExchangerComm.NO_RECORDS) {
            changeScreen(new AlertMessage(
                    this,
                    "Cannot find Business card exchange service on the devices",
                    scr));
        } else if (code == ExchangerComm.ERROR) {
            changeScreen(new AlertMessage(this,
                    "Errors during service discovery", scr));
        } else if (code == ExchangerComm.CANCELED) {
            changeScreen(new AlertMessage(this,
                    "Service discovery is canceled", scr));
        } else {
            // unknown error
            throw new RuntimeException("Internal error #27");
        }
    }

    public synchronized int resolveMultipleServices(Vector friendlyNames) throws InterruptedException {
        changeScreen(new ServiceListScreen(this, friendlyNames));

        wait(); // wait until the choice is made

        return selectedServiceIndex;

    }

    public byte[] getOwnBC() throws Exception {
        byte[] vCard = null;
        String uid;
        try {
            uid = Storage.getBCUID();
            vCard = AddressBook.getVCard(uid);
        } catch (Exception e) {
            throw new Exception("getOwnBC did not succeed");
        }
        return vCard;
    }

    public void onSendComplete(int code) {

        if (code == ExchangerComm.DONE) {
            String text = "Send was successful!";
            changeScreen(new AlertMessage(this, text,
                    scr));
        } else if (code == ExchangerComm.CANCELED) {
            changeScreen(new AlertMessage(this, "Send is canceled ",
                    scr));
        } else { // error

            changeScreen(new AlertMessage(this, "Errors during sending ",
                    scr));
        }
    }

    public void onReceiveComplete(int code) {
        if (code == ExchangerComm.DONE) {
            changeScreen(new AlertMessage(this, "Receiving was successful!",
                    scr));
        } else if (code == ExchangerComm.CANCELED) {
            changeScreen(new AlertMessage(this, "Receiving is canceled ",
                    scr));
        } else { // error
            changeScreen(new AlertMessage(this, "Errors during receiving ",
                    scr));
        }
    }

    public void onReceiveBC(byte[] vCard) throws Exception {
        AddressBook.setVCard(vCard);
    }

    /**
     * This is a helper methods which unblocks waiting code in
     * resolveMultipleServices()
     */
    public synchronized void unblock() {
        notify(); // let resolveMultipleServices complete
    }

    public void onGetComplete(int code) {
    }

    public void onPutComplete(int code) {
    }

    /**
     * Called in case of problems with Bluetooth OBEX server accepting connection
     * 
     */
    public void onServerError() {
        changeScreen(new AlertMessage(this,
                "Fatal Bluetooth error. Application will exit"));
        return;
    }
}