
BTBrowserMIDlet.jav
==========================

package org.klings.j2me.BTBrowser;

import javax.microedition.midlet.*;
import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.lcdui.*;
import java.util.*;
import java.io.*;
import javax.bluetooth.*;
import org.klings.wireless.j2me.*;
import org.klings.wireless.BluetoothNumbers.*;
import org.klings.j2me.BTBrowser.BTBrowserMIDlet.*;



public class BTBrowserMIDlet extends MIDlet implements CommandListener,
DiscoveryListener{

    private static class BTServiceAttributeId {
        private static int SDP_ICONURL;
        private static int SDP_CLIENTEEXECUTABLEURL;
        private static int SDP_DOCUMENTATIONURL;
        private static int SDP_SERVICEDESCRIPTION;
        private static int SDP_PROVIDERNAME;
        private static int SDP_SERVICEINFOTIMETOLIVE;
        private static int SDP_SERVICEAVAILABILITY;
        private static int SDP_BLUETOOTHPROFILEDESCRIPTORLIST;
        private static int SDP_SERVICENAME;

        public BTServiceAttributeId() {
        }
    }

    private static class BluetoothServiceRecordCanvas {

        public BluetoothServiceRecordCanvas() {
        }
    }

    
    
/* Reference to the Display object to do anything useful with UI*/
private Display display = null;
/* Reference to LocalDevice to do anything concerning Bluetooth */
private LocalDevice local=null;
/* Reference to a DiscoveryAgent to do inquiry or service searches */ 
private DiscoveryAgent agent=null;
/* Globally available Vectors for devices and services found */
private Vector deviceVector = null;
private Vector serviceVector = null;
/* Global Ticker used for most screens in this application */    
private Ticker tic = null;
/* 
     * Global UI list accessible to deviceDiscovered(...) so we can
* show devices and services as they are discovered, giving the user a
* feeling of progress in the program
*/
private List deviceList = null;
private List serviceList = null;
private String clientExecutableURL = null;
private String documentationURL = null;
private BluetoothServiceRecordCanvas rCanvas = null;
/* 
     * Global list of interesting service attributes used when populating and
* showing service records
*/
int[] attrs = {
BTServiceAttributeId.SDP_SERVICENAME,
BTServiceAttributeId.SDP_SERVICEDESCRIPTION,
BTServiceAttributeId.SDP_PROVIDERNAME,
BTServiceAttributeId.SDP_SERVICEINFOTIMETOLIVE,
BTServiceAttributeId.SDP_SERVICEAVAILABILITY,
BTServiceAttributeId.SDP_BLUETOOTHPROFILEDESCRIPTORLIST,
BTServiceAttributeId.SDP_DOCUMENTATIONURL,
BTServiceAttributeId.SDP_CLIENTEEXECUTABLEURL,
BTServiceAttributeId.SDP_ICONURL,
};
/* Globally available commands used for most menus */
Command exitCommand = new Command("Exit",Command.EXIT,2);
Command searchCommand = new Command("New Search",Command.SCREEN, 1);
    Command backCommand = new Command("Back", Command.BACK, 1);
Command cancelCommand = new Command("Cancel",Command.CANCEL,1);
Command openURL = new Command("Open URL",Command.CANCEL,2);
/* Integer to keep track of which menu is active */
int currentMenu = 0;
/* Boolean stating if an inquriy is in progress or not */
boolean inquiring = false;
/* 
     * Integer to keep track of service searches. Needed to cancel an
* ongoing service search
*/ 
    int serviceSearch = 0;
public void startApp() {
display = Display.getDisplay(this);
Alert a = null;
try {
            local = LocalDevice.getLocalDevice();
        }catch(BluetoothStateException bse) {
a = new Alert("Bluetooth error",
"Either Bluetooth must be turned on, or your "+
"device does not support JABWT",
null,AlertType.ERROR);
a.setTimeout(Alert.FOREVER);
a.addCommand(exitCommand);
a.setCommandListener(this);
        }
       
tic = new Ticker("By Klings, www.klings.org/nowires");
mainMenu(a);
    }
public void pauseApp() {
display = null;
local=null;
//attrs = null;
tic = null;
    }
public void destroyApp(boolean unconditional) {
                
        notifyDestroyed();
    }
/*
     * mainMenu() will present the user a list of cached and preknown devices,
* and provide a menu to initiate device discovery (inquiry) in order to
* find nearby Bluetooth devices
*/
    private void mainMenu(Alert a) {
List knownDevices = new List("Cached/known devices",List.IMPLICIT);
if (deviceVector == null) deviceVector = new Vector();
if (agent == null) agent = local.getDiscoveryAgent();
/* Retrieve PREKNOWN devices and add them to our Vector */
RemoteDevice[] devices = agent.retrieveDevices(
DiscoveryAgent.PREKNOWN);
String name = null;
if (devices != null) {
            
/* 
 * Synchronize on vector to obtain object lock before loop.
 * Else, object lock will be obtained every iteration.
 */
            synchronized(deviceVector) {
for (int i = devices.length-1;i >=0;i--) {
                    deviceVector.addElement(devices[i]);
try {
                        name = devices[i].getFriendlyName(false);
                    }catch (IOException ioe) {
name = devices[i].getBluetoothAddress();
}
if (name.equals("")) 
name = devices[i].getBluetoothAddress();
knownDevices.insert(0,name,null);
                }
            } //End synchronized
        }
/* Retrieve cached devices and add them to our Vector */
devices = null; devices = agent.retrieveDevices(
DiscoveryAgent.CACHED);
if (devices !=null) {
synchronized(deviceVector) {
                for (int i = devices.length-1;i >=0;i--) {
                    deviceVector.addElement(devices[i]);
try {
                        name = devices[i].getFriendlyName(false);
}catch (IOException ioe) {
name = devices[i].getBluetoothAddress();
}
if (name.equals(""))
name = devices[i].getBluetoothAddress();
knownDevices.insert(0,name,null);
                }
            }
        }
/* Indicate to user if the Vector is empty */
if (deviceVector.isEmpty()) {
            knownDevices.append("Empty",null);
}
knownDevices.setTicker(tic);
knownDevices.addCommand(exitCommand);
knownDevices.addCommand(searchCommand);
knownDevices.setCommandListener(this);
/* If we have an Alert, show it... */
if (a ==null ) display.setCurrent(knownDevices);
else display.setCurrent(a,knownDevices);
currentMenu = 1;
    }
/*
     * deviceScreen() will show the user a list of devices found 
* during device discovery (inquiry)
*/
    private void deviceScreen(Alert a) {
/* 
         * if currentmenu < 3 we are in screen with known/cached devices or
* screen with discovered devices and have issued a device search
* deviceList is then reinitialized by startInquiry(), hence we 
* must add these commands again
*/
    
        if (currentMenu < 3) {
deviceList.setTicker(tic);
if(inquiring ) {
                deviceList.setTitle("Please wait...");
deviceList.addCommand(cancelCommand);
}else {
                deviceList.setTitle("Devices:");
deviceList.removeCommand(cancelCommand);
deviceList.addCommand(exitCommand);
deviceList.addCommand(searchCommand);
deviceList.addCommand(backCommand);
            }
deviceList.setCommandListener(this);
        }
/* Display Alert if any... */
         
        if (a == null) display.setCurrent(deviceList);
else display.setCurrent(a,deviceList);
currentMenu = 2;
    }
/*
     * startInquiry() will reinitialize the list of devices, and initiate
* a device discovery (inquiry) repopulating the list of devices
*/
    private void startInquiry() {
Alert a = new Alert("Inquiry status",null,null,AlertType.INFO);
if (agent ==null) agent = local.getDiscoveryAgent();
/* Get rid of old search results in vector and deviceList */
deviceVector.removeAllElements();
deviceList = null; deviceList = new List("Devices",List.IMPLICIT);
/* Start the actual inquiry */
try {
            inquiring = agent.startInquiry(DiscoveryAgent.GIAC, this);
}catch(BluetoothStateException bse) {
a.setType(AlertType.ERROR);
a.setString("Bluetooth error while starting inquiry");
mainMenu(a);
return;
        }
if (inquiring) {
            a.setString("Inquiry started");
deviceScreen(a);
        }
else {
            a.setType(AlertType.ERROR);
a.setString("Error starting inquiry");
//With no Inquiry we have no need for this any more.
deviceList = null;
mainMenu(a);
        }
    }
/*
     * getFriendlyNames() will contact all devices in the deviceVector and
* retrieve their friendly names, if available
*/
    private void getFriendlyNames() {
        String name = null;
for (int i = deviceVector.size() -1; i>= 0;i--) {
try {
                name = ((RemoteDevice)
deviceVector.elementAt(i)).getFriendlyName(false);
            }catch (IOException ioe) {
/*Appendix A BTBrowserMIDlet.java 85
             * An IOException may occur if the remote device can not be
 * contacted or the remote device could not provide its name.
 * In that case we leave the Bluetooth address in the list,
 * and move on to the next device found.
 */
                continue;
}
if (!name.equals("")) {
                deviceList.set(i, name,null);
}
        }
    }
/*
     * startServiceSearch() will initiate a service search on the supplied
* remote device.
*/    
    private void startServiceSearch(RemoteDevice rDevice) {
Alert a = null;
//Prepare serviceVector
if (serviceVector == null) serviceVector = new Vector();
else serviceVector.removeAllElements();
serviceList = null; serviceList = new List("",List.IMPLICIT);
try {
            serviceList.setTitle( rDevice.getFriendlyName(false));
}catch (IOException ioe) {
serviceList.setTitle(rDevice.getBluetoothAddress());
}
                
/* 
         * Search for services containing the PublicBrowseRoot UUID (0x1002)
* Should give us all public browseable services
*/
UUID[] uuids = new UUID[1];
uuids[0] = new UUID(0x1002);
/*
         * Start the actual service search, using the attrs array initialized
* earlier, the UUID array and the remote device we want to do a
* service search on
*/
        try {
            serviceSearch = agent.searchServices(attrs, uuids, rDevice, this);
}catch (BluetoothStateException bse) {
a = new Alert("Bluetooth error", "Error starting service search",
null, AlertType.ERROR);
deviceScreen(a);
return;
        }
a = new Alert("Status","Service search started. Please wait!",
null, AlertType.INFO);
        deviceScreen(a);
    }
/*
     * serviceScreen() will present a list of discovered services to the user 
*/
    private void serviceScreen(Alert a) {
                      
        //Make sure we only add these commands once
if (currentMenu <= 2) {
serviceList.setTicker(tic);
if(serviceSearch == 0) {
                serviceList.addCommand(exitCommand);
serviceList.addCommand(backCommand);
serviceList.removeCommand(cancelCommand);
            }else{
serviceList.addCommand(cancelCommand);
}
serviceList.setCommandListener(this);
        }
if (a == null) display.setCurrent(serviceList);
else display.setCurrent(a,serviceList);
currentMenu = 3;
    }
/*
     * showService() will create a recordCanvas showing service attributes
* to the user
*/
    private void showService(int index) {
        
ServiceRecord s = (ServiceRecord) serviceVector.elementAt(index);
if (rCanvas == null){
rCanvas = new BluetoothServiceRecordCanvas(s);
rCanvas.addCommand(exitCommand);
rCanvas.addCommand(backCommand);
rCanvas.setCommandListener(this);
}else{
        rCanvas.setServiceRecord(s);
rCanvas.removeCommand(openURL);
     }
clientExecutableURL = rCanvas.getClientExecutableURL();
        documentationURL = rCanvas.getDocumentationURL();
if (clientExecutableURL !=null || documentationURL != null)
rCanvas.addCommand(openURL);
//rCanvas.setTicker(tic);
display.setCurrent(rCanvas);
currentMenu = 4;
        
    }
private void openURLScreen(){
List list = new List("Open URL",List.IMPLICIT);
list.append("Documentation",null);
list.append("Client Executable",null);
list.addCommand(backCommand);
list.setCommandListener(this);
currentMenu = 5;
}
private void openURL(String url){
boolean mustExit = false;
Alert a = new Alert("Error","",null,AlertType.ERROR);
try {
mustExit = platformRequest(url);
} catch (ConnectionNotFoundException e) {
a.setString("This device cannot open URLs requested by Java "+
"programs. See http://www.klings.org/nowires "+
"for information.");
display.setCurrent(a,rCanvas);
currentMenu = 4;
return;
}
if (mustExit){
a.setType(AlertType.INFO);
a.setTitle("Notification");
a.setString("The URL MAY be opened when this application exits."+
" Choose exit to open URL now.");
display.setCurrent(a,rCanvas);
currentMenu = 4;
}
    }
/*
     * deviceDiscovered() is called by the JABWT implementation when a device
* is discovered during device discovery (inquiry)
*/
    public void deviceDiscovered(javax.bluetooth.RemoteDevice remoteDevice,
javax.bluetooth.DeviceClass deviceClass) {
//Add device to vector in case of further use
deviceVector.addElement(remoteDevice);
/* Add vector to active list, making devices show up as they are added
         * Add only BT address, since getting the name requires going on air
* Will get friendly name later, device is probably quite busy now
*/
        deviceList.append(remoteDevice.getBluetoothAddress(),null);
    }
/*
     * inquiryCompleted() is called by the JABWT implementation when device88 BTBrowserMIDlet.java Appendix A
     * discovery (inquiry) is completed
*/
    public void inquiryCompleted(int param) {
        inquiring = false;
Alert a = new Alert("Inquiry status",null,null,AlertType.INFO);
switch(param) {
            
/*
 * If inquiry completed normally, give the user an alert stating
 * that no devices were found, or the number of devices discovered.
 * Also, retrive friendly names, if devices were discoverd.
 */
            case DiscoveryListener.INQUIRY_COMPLETED:
if (deviceVector.size() == 0) {
                    a.setString("No devices found!");
deviceList.append("Empty",null);
                }else {
getFriendlyNames();
a.setString(deviceVector.size() + " devices found!");
                }
deviceScreen(a);
break;
            /*
             * Alert the user if an error occured during device discovery
* (inquiry). Show list of devices found before error occured.
*/    
            case DiscoveryListener.INQUIRY_ERROR:
                a.setType(AlertType.ERROR);
if(deviceVector.size() > 0) {
                    a.setString("Error occured, but " + deviceVector.size()+
" devices found anyway!");
getFriendlyNames();
deviceScreen(a);
                }
else{ 
                    a.setString("Error occured during inquiry.");
mainMenu(a);
                }    
break;
/*
             * If the user requests termination of the device discovery
* (inquiry), alert the user that the process is actually
* terminated.
*/
            case DiscoveryListener.INQUIRY_TERMINATED:
a.setString("Search terminated");
if(deviceVector.size() > 0) {
getFriendlyNames();
deviceScreen(a);
}else{
mainMenu(a);
}
                break;
        }
    }
/*
     * servicesDiscovered() is called by the JABWT when services are discovered
* during service search. The transID parameter identifies the particular
* service search that returned results. The serviceRecord array is the
* services found during the search. 
*/
    public void servicesDiscovered(int transID,
ServiceRecord[] serviceRecord) {
DataElement nameElement = null;
synchronized(serviceVector) {
for (int i = 0;i < serviceRecord.length ; i++) {
nameElement = (DataElement) 
serviceRecord[i].getAttributeValue(0x100);
if (nameElement != null 
&& nameElement.getDataType() == DataElement.STRING) {
                    serviceList.append((String) nameElement.getValue(),null);
serviceVector.addElement(serviceRecord[i]);
                }
            }
        }
    }
/*
     * serviceSearchCompleted() is called by the JABWT implementation when
* service search completes. the transID parameter identifies a particular
* service search, the responseCode indicates why the service search is
* ended.
*/
    public void serviceSearchCompleted(int transID, int responseCode) {
        
/* 
 * serviceSearch is a handle to the active service search. Set this to
 * 0 since the search is ended.
 */
serviceSearch = 0;
        Alert a = new Alert("Search status",null,null,AlertType.INFO);
switch(responseCode) {
            
/*
 * Service search completed normally. Show the user the results.
 */
            case DiscoveryListener.SERVICE_SEARCH_COMPLETED:
                a.setString("Service search complete");
serviceScreen(a);
break;
/*
             * The remote device was not reachable, making it really hard to
* search for services.
*/
            case DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
a.setString("Device not reachable");
deviceScreen(a);
break;
            /*
             * Some error occured during service search, alert the user.
*/
            case DiscoveryListener.SERVICE_SEARCH_ERROR:
                a.setType(AlertType.ERROR);
a.setString("Error during service search");
deviceScreen(a);
break;
/*
             * No service were returned by the remote device, alert the user.
*/
            case DiscoveryListener.SERVICE_SEARCH_NO_RECORDS:
                a.setString("No services found");
deviceScreen(a);
break;
            /*
             * Service search termination requested by user, alert the user
* that the search is indeed terminated.
*/
            case DiscoveryListener.SERVICE_SEARCH_TERMINATED:
                a.setString("Search terminated");
deviceScreen(a);
break;
        }
    }
/*
     * The commandAction() is the central nerve of a command-driven MIDlet.
* We must check wich command is selected and also keep track of which
* menu that was active when the command was selected. We make use of the
* currentMenu Integer to achieve this.
*/
    public void commandAction(Command c,Displayable d) {
if (c == exitCommand) destroyApp(true);
else if(c == searchCommand) {
            startInquiry();
}
else if(c == backCommand) {
/*
 * User wants to go back, check where we are and fulfillAppendix A BTBrowserMIDlet.java 91
         * the request.
 */
            switch(currentMenu) {
case 2:
                    mainMenu(null);
break;
                case 3:
deviceScreen(null);
break;
                case 4:
serviceScreen(null);
break;
                case 5:
display.setCurrent(rCanvas);
currentMenu = 4;
break;
            }
        }else if(c == cancelCommand){
/*
 * The user wants to cancel either a device discovery or a service
 * search. Check where we are, and fulfill the request.
 */
            switch(currentMenu) {
case 2:
                    if (inquiring) {
inquiring = !agent.cancelInquiry(this);
if (inquiring) {
                        deviceScreen(new Alert("Error",
"Could not stop inquiry or inquiry not started",
null, AlertType.ERROR));
return;
                    }
}else if (serviceSearch > 0 
&& agent.cancelServiceSearch(serviceSearch)) {
                        deviceScreen(new Alert("Status",
"Service search terminated",null,
AlertType.INFO));
                    }
serviceSearch = 0;
break;
                case 3:
if(!agent.cancelServiceSearch(serviceSearch)) {
                        serviceScreen(new Alert("Error",
"No active service search",null,
AlertType.ERROR));
                    }
break;
            }
        }else if (c == openURL){
openURLScreen();
    }else if (c == List.SELECT_COMMAND) {
            
/*
 * The user has selected something from a list. Find out where
 * we are, get the List currently displayed and act according to
 * this.
 */
            List list = (List) display.getCurrent();
int index = list.getSelectedIndex();
switch (currentMenu) {
case 1: // Main list of known devices
case 2: //List of newly found devices
if (serviceSearch == 0 && ! deviceVector.isEmpty())
                        startServiceSearch(
(RemoteDevice)deviceVector.elementAt(index));
                    break;
                case 3: //Browse service
if(! serviceVector.isEmpty()) showService(index);
break;
case 5: //The user wants to open an URL
switch(index){
case 0:
openURL(documentationURL);
break;
case 1:
openURL(clientExecutableURL);
break;
}
            }//End switch for list-index
        }// End if for List-command
    }//End commandaction
}//End all
================================================================================
Server
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.klings.j2me.BTBrowser;

package org.klings.wireless.j2me.BTBenchmark;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.bluetooth.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
import org.klings.wireless.j2me.*;

public class Server extends MIDlet implements CommandListener, Runnable{
/* Display and Bluetooth LocalDevice */
private Display display = null;
private LocalDevice local = null;
private List list = null;
private Ticker tic = null;
/* Commands */
private Command exitCommand = new Command("Exit",Command.EXIT,2);
private Command startCommand = new Command("Start",Command.SCREEN,2);
private Command settingsCommand = new Command("Settings",Command.SCREEN,2);
private Command backCommand = new Command("Back", Command.BACK, 1);
private Command btInfoCommand = new Command("BTInfo",Command.SCREEN,2);
/* Notifier for client connections */
private StreamConnectionNotifier server = null;
/* Connection for communication */
private StreamConnection conn = null;
private InputStream in = null;
private OutputStream out = null;
/* Connection parameters */
private boolean authenticate = false;
private boolean encrypt = false;
private boolean authorize = false;
private boolean master = false;
/* Canvas to show status to user */
private StatusCanvas s=null;
/* Initialized in createService(), defined globally so it is accessible
 * by the communicating thread.
 */
private String connectionURL;
/* Thread for blocking functionality */
private Thread t = null;
/* Default constructor */
public Server() {
super();
}
protected void startApp() throws MIDletStateChangeException {
display = Display.getDisplay(this);
tic = new Ticker("By Klings, www.klings.org/nowires");
mainMenu(null);
}
protected void pauseApp() {
tic = null;
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
/* 
 * Ensure that cleanUp() is called before MIDlet exits. cleanUp()
 * will close the notifier, which will remove the service record from
 * device Bluetooth SDDB. Very important!
 */
cleanup();
/*
 * If the communication Thread is waiting for clients, an exception
 * occurs when we close the notifier. The thread will terminate,
 * wait for it to terminate.
 */
if(t!=null){
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
notifyDestroyed();
}
public void commandAction(Command c, Displayable arg1) {
if (c == exitCommand) {
try {
destroyApp(true);
} catch (MIDletStateChangeException e) {
}
}
else if(c == startCommand){
/*
 *  Start a server thread. createService() returns true
 * if the service was created successfully.
 */
if (createService()){
/* Show status screen to user */
s = new StatusCanvas();
s.waitForClient(connectionURL);
s.addCommand(exitCommand);
s.setCommandListener(this);
s.setTicker(tic);
display.setCurrent(s);
t = new Thread(this);
t.start();
}else{
mainMenu(new Alert("Error","Error creating service",null,
AlertType.ERROR));
}
}else if(c == settingsCommand){
settings();
}else if (c == backCommand){
mainMenu(null);
}else if (c == btInfoCommand){
BluetoothInfoCanvas btic = new BluetoothInfoCanvas();
btic.addCommand(backCommand);
btic.setCommandListener(this);
display.setCurrent(btic);
}else if (c == List.SELECT_COMMAND) {
            
/* There is only one list. Check what the user selected */
List list = (List) display.getCurrent();
int index = list.getSelectedIndex();
switch (index){
case 0:
authenticate = !authenticate;
if(!authenticate) {
encrypt = false;
authorize = false;
}
break;
case 1:
encrypt = !encrypt;
if(encrypt) authenticate = true;
break;
case 2:
authorize = !authorize;
if (authorize) authenticate = true;
break;
case 3:
master = !master;
break;
}
            
/* Update settings screen so it reflects the user's choice */
settings();
}
}
/* Display list of connection settings */
private void settings() {
List sett = new List("Settings:",List.IMPLICIT);
sett.append("Authenticate: " + (authenticate?"On":"Off"),null);
sett.append("Encrypt: " + (encrypt?"On":"Off"),null);
sett.append("Authorize: " + (authorize?"On":"Off"),null);
if ("true".equals(LocalDevice.getProperty("bluetooth.master.switch")))
sett.append("Master: " + (master?"Yes":"No"),null);
sett.addCommand(startCommand);
sett.setCommandListener(this);
display.setCurrent(sett);
}
/* Display main menu */
private void mainMenu(Alert a){
list = new List("Benchmark Server",List.IMPLICIT);
list.setTicker(tic);
list.addCommand(exitCommand);
list.addCommand(startCommand);
list.addCommand(settingsCommand);
list.addCommand(btInfoCommand);
list.setCommandListener(this);
if(a == null){
display.setCurrent(list);
}else display.setCurrent(a,list);
}
/* Create ServiceRecord, set desired attributes */
private boolean createService(){
ServiceRecord record = null;
Alert a = new Alert("Error","",null,AlertType.ERROR);
a.setTimeout(Alert.FOREVER);
/* Get the Bluetooth LocalDevice */
try {
local = LocalDevice.getLocalDevice();
local.setDiscoverable(DiscoveryAgent.GIAC);
} catch (BluetoothStateException e) {
a.setString("Error getting localdevice or setting discovery mode");
display.setCurrent(a,list);
e.printStackTrace();
return false;
}
String param ="";
/* Add parameters to connection URL */
if(encrypt) param = "encrypt=true;";
else if(authorize) param="authorize=true;";
else if(authenticate) param="authenticate=true;";
param += "name=BTBench";
if(master) param +=";master=true";
connectionURL = "btspp://localhost:66ca80886d1f11d88526000bdb544cb1;"
+ param;
/* Get the notifier, will also generate a ServiceRecord */
try {
server = (StreamConnectionNotifier) Connector.open(connectionURL);
} catch (IOException e1) {
return false;
}
/* Get the ServiceRecord associated with the notifier */
try {
record = local.getRecord(server);
}
catch (IllegalArgumentException iae){
return false;
}
/* 
 * Manipulate the ServiceRecord to meet our needs. Some code is
 * disabled, but is included to show how attributes are set.
 */
DataElement elm = null;
/* 
 * Set public browse root in browsegrouplist, making service
 * public browseable
 */
elm = new DataElement(DataElement.DATSEQ);
elm.addElement(new DataElement(DataElement.UUID,new UUID(0x1002)));
record.setAttributeValue(0x0005,elm);
/* Set service description */ 
elm = new DataElement(DataElement.STRING,"BT Benchmark service");
record.setAttributeValue(0x101,elm);
/* Set service provider name */
elm = new DataElement(
DataElement.STRING,"Klings, NoWires Research Group");
record.setAttributeValue(0x102,elm);
/* Set serviceInfoTimeToLive */
/*elm = new DataElement(DataElement.U_INT_4,10000);
record.setAttributeValue(0x0007,elm);*/
/* Set serviceAvailability */
/*elm = new DataElement(DataElement.U_INT_1,255);
record.setAttributeValue(0x0008,elm);*/
/* Set documentationURL */
elm = new DataElement(
DataElement.URL,"http://wap.klings.org/btbenchmark.wml");
record.setAttributeValue(0x000A,elm);
/* Set clientExecutableURL */
elm = new DataElement(
DataElement.URL,"http://wap.klings.org/java/btbenchmark.jad");
record.setAttributeValue(0x000B,elm);
/* Set iconURL */
/*elm = new DataElement(
 *  DataElement.URL,"http://klings.org/java/BTBenchmark.ico");
record.setAttributeValue(0x000C,elm);*/
/* Update the record, else changes are lost */
try {
local.updateRecord(record);
} catch (ServiceRegistrationException e3) {
return false;
}
return true;
}
/* run() method executed by communication thread */
public void run() {
/* 
 * If the notifier is not available, a service has not been
 * created.
 */
if(server == null) return;
Alert a = new Alert("Error","",null,AlertType.ERROR);
a.setTimeout(Alert.FOREVER);
/* 
 * Open the notifier. This is a blocking operation. Now the
 * ServiceRecord will be entered in the Bluetooth SDDB and
 * the server is ready for client connections. 
 */
try {
conn = server.acceptAndOpen();
}
catch (ServiceRegistrationException sre){
a.setString("Error creating service record");
display.setCurrent(a,list);
cleanup();
return;
}
catch (IOException e2) {
if (t != null){
a.setString("Error starting server. " + e2.getMessage());
display.setCurrent(a,list);
}
cleanup();
return;
}
/* A client has connected! Retrieve information about the
 * remote device and display it to the user.
 */
RemoteDevice dev = null;
String name,address;
boolean authorized = false;
try {
dev = RemoteDevice.getRemoteDevice(conn);
name = dev.getFriendlyName(false);
address = dev.getBluetoothAddress();
authorized = dev.isAuthorized(conn);
} catch (IOException e) {
name = "Unknown";
address = "Unknown";
}
s.connectedToClient(name,address,dev.isAuthenticated(),
dev.isEncrypted(),authorized);
display.setCurrent(s);
/* 
 * The user now knows who connected. Get streams and start
 * communication.
 */
try {
in = conn.openInputStream();
out = conn.openOutputStream();
} catch (IOException e4) {
a.setString("Error opening input/output streams:" +
e4.getMessage());
display.setCurrent(a,list);
cleanup();
t = null;
return;
}
DataInputStream dais = new DataInputStream(in);
byte[] data = new byte[512];
//int data;
long timer = 0;
boolean keepOn = true;
int bytesRead = 0;
int iterations = 0;
/* read the number of iterations */
try {
iterations = dais.readInt();
}catch (EOFException eof ){
a.setString("EOF on first read.");
display.setCurrent(a,list);
cleanup();
list.addCommand(startCommand);
return;
} catch (IOException e5) {
a.setString("Error on first read.");
display.setCurrent(a,list);
cleanup();
list.addCommand(startCommand);
return;
}
/* Get the time and do actual communication */
try{
timer = System.currentTimeMillis();
for (int i = iterations; i>0;i--){
bytesRead = dais.read(data,0,data.length);
out.write(0);
out.flush();
}
timer = System.currentTimeMillis() - timer;
}catch (IOException ioe) {
a.setString(bytesRead +
" bytes read before communication error occured. " +
ioe.getMessage());
display.setCurrent(a,list);
cleanup();
list.addCommand(startCommand);
return;
}
/* Communication complete. Cleanup connections */
cleanup();
long sec = timer / 1000;
long transferred = iterations/2;
/* Display statistics to user */
a.setType(AlertType.INFO);
a.setTitle("Success!");
a.setString("Read " + transferred +" KB in " + sec + " seconds.\n" 
+transferred/sec + " KBps");
display.setCurrent(a,list);
list.addCommand(startCommand);
list.addCommand(settingsCommand);
list.setTitle("Run complete.");
}
/* Close streams and notifier */
private void cleanup() {
try {
if(in != null){
in.close();
}
if(out != null){
out.close();
}
if (conn != null) {
conn.close();
}
if (server != null){
server.close();
}
}catch (IOException ioe){
// Error occurred.
}
}
}
============================================================
Client

==========================



package org.klings.wireless.j2me.BTBenchmark

import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.*;
import java.util.*;
import java.io.*;
import javax.microedition.io.*;
import javax.bluetooth.*;
import org.klings.wireless.j2me.*;
public class Client extends MIDlet implements CommandListener,
     DiscoveryListener,
     Runnable{

    private static class BluetoothInfoCanvas {

        public BluetoothInfoCanvas() {
        }
    }

    private static class StatusCanvas {

        public StatusCanvas() {
        }
    }
    private Display display = null;
private LocalDevice local=null;
private DiscoveryAgent agent=null;
/* Vectors to store devices an services in */
private Vector deviceVector = null;
private Vector serviceVector = null;
private Ticker tic = null;
/* Global list accessible to deviceDiscovered(...) */
private List deviceList = null;
private List serviceList = null;
/* lobal serviceRecord accessible to several threads */
private ServiceRecord globalRecord = null;
private StreamConnection conn = null;
private DataOutputStream out = null;
private InputStream in = null;
/* Connection parameters */
boolean authenticate,encrypt,master=false;
private int iterations = 0;
private Command exitCommand = new Command("Exit",Command.EXIT,2);
private Command searchCommand = new Command("New Search",Command.SCREEN, 1);
private Command backCommand = new Command("Back", Command.BACK, 1);
private Command cancelCommand = new Command("Cancel",Command.CANCEL,1);
private Command settingsCommand = new Command("Settings",Command.SCREEN,1);
private Command btInfoCommand = new Command("BTInfo",Command.SCREEN,2);
int currentMenu = 0;
/* Keep track of ongoing device discoveries */
boolean inquiring = false;
/* Keep track of ongoing service discoveries */
int serviceSearch = 0;
public void startApp() {
display = Display.getDisplay(this);
try {
            local = LocalDevice.getLocalDevice();
        }catch(BluetoothStateException bse) {
System.err.println("LocalDevice error");
}
tic = new Ticker("By Klings, www.klings.org/nowires");
mainMenu(null);
    }
public void pauseApp() {
        display = null;
local = null;
tic = null;
    }
public void destroyApp(boolean unconditional) {
cleanUp();
notifyDestroyed();
    }
/* Main menu, list of cached/known Bluetooth devices */
private void mainMenu(Alert a) {
List knownDevices = new List("Cached/known devices",List.IMPLICIT);
if (deviceVector == null) deviceVector = new Vector();
if (agent == null) agent = local.getDiscoveryAgent();
RemoteDevice[] devices = agent.retrieveDevices(
DiscoveryAgent.PREKNOWN);
String name = null;
if (devices != null) {
            
/* 
 * Synchronize on vector before running through loop, since
 * Vector methods are thread safe. We obtain the object lock
 * on the Vector once, instead of every iteration. Add devices
 * to the deviceVector.
 */
            synchronized(deviceVector) {
for (int i = devices.length-1;i >=0;i--) {
                    deviceVector.addElement(devices[i]);
try {
                        name = devices[i].getFriendlyName(false);
                    }catch (IOException ioe) {
name = devices[i].getBluetoothAddress();
}
if (name.equals("")) 
name = devices[i].getBluetoothAddress();
knownDevices.append(name,null);
                }
            } //End synchronized
        }
devices = agent.retrieveDevices(DiscoveryAgent.CACHED);
if (devices !=null) {
synchronized(deviceVector) {
                for (int i = devices.length-1;i >=0;i--) {
                    deviceVector.addElement(devices[i]);
try {
                        name = devices[i].getFriendlyName(false);
}catch (IOException ioe) {
name = devices[i].getBluetoothAddress();
                    }
if (name.equals(""))
name = devices[i].getBluetoothAddress();
knownDevices.append(name,null);
                }
            }
        }
/* No cached/known devices, notify the user */
if (deviceVector.isEmpty()) {
            knownDevices.append("Empty",null);
}
knownDevices.setTicker(tic);
knownDevices.addCommand(exitCommand);
knownDevices.addCommand(searchCommand);
knownDevices.addCommand(btInfoCommand);
knownDevices.setCommandListener(this);
/* Show Alert, if available */
if (a ==null ) display.setCurrent(knownDevices);
else display.setCurrent(a,knownDevices);
currentMenu = 1;
    }
/* Show list of discovered devices */
private void deviceScreen(Alert a) {
/* if currentmenu < 3 we are in screen with known/cached devices or
         * screen with discovered devices and have issued a device search
* deviceList is then reInitialized by startInquiry(), hence we
*  must add these commands again
*/
        if (currentMenu < 3) {
deviceList.setTicker(tic);
if(inquiring) {
                deviceList.addCommand(cancelCommand);
}else{
deviceList.removeCommand(cancelCommand);
deviceList.addCommand(exitCommand);
deviceList.addCommand(searchCommand);
deviceList.addCommand(backCommand);
            }
deviceList.setCommandListener(this);
        }
if (a == null) display.setCurrent(deviceList);
else display.setCurrent(a,deviceList);
currentMenu = 2;
    }
/* Start device discovery */
    private void startInquiry() {
Alert a = new Alert("Inquiry status",null,null,AlertType.INFO);
if (agent ==null) agent = local.getDiscoveryAgent();
/* Remove old search results in vector and deviceList */
deviceVector.removeAllElements();
deviceList = new List("Nearby devices",List.IMPLICIT);
/* Start the actual device discovery */
try {
            inquiring = agent.startInquiry(DiscoveryAgent.GIAC, this);
}catch(BluetoothStateException bse) {
a.setType(AlertType.ERROR);
a.setString("Bluetooth error while starting inquiry");
mainMenu(a);
return;
        }
/* Notify the user if inquiry was started or not */
if (inquiring) {
            a.setString("Inquiry started");
deviceScreen(a);
        }
else {
            a.setType(AlertType.ERROR);
a.setString("Error starting inquiry");
/* With no Inquiry we have no need for this any more. */
deviceList = null;
mainMenu(a);
        }
    }
/* Retrieve friendly names for all devices in deviceVector */
private void getFriendlyNames() {
String name = null;
synchronized(deviceVector){
for (int i = deviceVector.size() -1; i>= 0;i--) {
try {
name = ( (RemoteDevice)
deviceVector.elementAt(i)).getFriendlyName(false);
}catch (IOException ioe) {
continue;
}
if (!name.equals("")) {
deviceList.set(i, name,null);
}
}// End for
}// End synchronized 
}
/* Start service discovery on remote device */
private void startServiceDiscovery(RemoteDevice rDevice) {
Alert a = null;
/* Prepare serviceVector and service list*/
if (serviceVector == null) serviceVector = new Vector();
else serviceVector.removeAllElements();
serviceList = new List("",List.IMPLICIT);
try {
            serviceList.setTitle( rDevice.getFriendlyName(false));
}catch (IOException ioe) {
serviceList.setTitle(rDevice.getBluetoothAddress());
}
UUID[] uuids = new UUID[1];
/* Add the BTBenchmark UUID to an array */
uuids[0] = new UUID("66ca80886d1f11d88526000bdb544cb1",false);
/* 
         * Retrieve default attributes, services with BTBenchmark UUID on
* the remote device.
*/
        try {
            int transid = agent.searchServices(null, uuids, rDevice, this);
}catch (BluetoothStateException bse) {
a = new Alert("Bluetooth error", "Error starting service search",
null, AlertType.ERROR);
deviceScreen(a);
return;
        }
    }
/* Select amount of data to transfer */
private void selectDataScreen(Alert a) {
        
List tList = new List("Select amount of data ",List.IMPLICIT);
  tList.append("10KB",null);
        tList.append("100KB",null);
tList.append("500KB",null);
tList.append("1000KB",null);
    
tList.addCommand(settingsCommand);
tList.addCommand(backCommand);
tList.setCommandListener(this);
if (a == null) display.setCurrent(tList);
else display.setCurrent(a,tList);
currentMenu = 3;
    }
/* 
     * Set the number of iterations to use by the thread when communicating,
* then start the communication Thread.
*/
    private void doTransfer(int index) {
        
switch(index){
case 0: iterations = 20; break;
case 1: iterations = 200; break;
case 2: iterations = 1000; break;
case 3: iterations = 2000; break;
}
Thread t = new Thread(this);
t.start();
}
/* Display settings menu */
private void settingsScreen(){
List settings = new List("Settings",List.IMPLICIT);
settings.append("Authenticate: " + (authenticate? "Yes":"No"),null);
settings.append("Encrypt: " + (encrypt? "Yes":"No"),null);
if ("true".equals(LocalDevice.getProperty("bluetooth.master.switch")))
settings.append("Master: " + (master? "Yes":"No"),null);
settings.addCommand(backCommand);
settings.setCommandListener(this);
display.setCurrent(settings);
currentMenu = 31;
}
/* A device is discovered. Add it to the deviceVector */
public void deviceDiscovered(javax.bluetooth.RemoteDevice remoteDevice,
javax.bluetooth.DeviceClass deviceClass) {
/* Add device to vector in case of further use */
deviceVector.addElement(remoteDevice);
/* 
         * Add device to active list, making devices show up as they are
* discoverd. Add only BT address, getting the name requires the 
* device to go on air and the device is probably quite busy now. 
*/
deviceList.append(remoteDevice.getBluetoothAddress(),null);
    }
/* Device discovery completed. Get friendly names. */
public void inquiryCompleted(int status) {
        inquiring = false;
Alert a = new Alert("Inquiry status",null,null,AlertType.INFO);
/* Check status */
switch(status) {
case DiscoveryListener.INQUIRY_COMPLETED:
if (deviceVector.size() == 0) {
                    a.setString("No devices found!");
deviceList.append("Empty",null);
                }else {
                    getFriendlyNames();
a.setString(deviceVector.size() + " devices found!");
                }
deviceScreen(a);
break;
            case DiscoveryListener.INQUIRY_ERROR:
a.setType(AlertType.ERROR);
a.setString("Error occured.");
mainMenu(a);
break;
            case DiscoveryListener.INQUIRY_TERMINATED:
a.setString("Search terminated");
if(deviceVector.size() > 0) {
getFriendlyNames();
deviceScreen(a);
}else{
mainMenu(a);
}
break;
        }
    }
/* ServiceSearch completed. */
public void serviceSearchCompleted(int transID, int respCode) {
        serviceSearch = 0;
Alert a = new Alert("Search status",null,null,AlertType.INFO);
/* Check resonse Code */
switch(respCode) {
case DiscoveryListener.SERVICE_SEARCH_COMPLETED:
                a.setString("Service found!");
selectDataScreen(a);
break;
            case DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
a.setString("Device not reachable");
deviceScreen(a);
break;
            case DiscoveryListener.SERVICE_SEARCH_ERROR:
a.setType(AlertType.ERROR);
a.setString("Error during service search");
deviceScreen(a);
break;
            case DiscoveryListener.SERVICE_SEARCH_NO_RECORDS:
a.setString("No services found");
deviceScreen(a);
break;
            case DiscoveryListener.SERVICE_SEARCH_TERMINATED:
                a.setString("Search terminated");
deviceScreen(a);
break;
        }
    }
/* Services were discovered. */
public void servicesDiscovered(int transID,
ServiceRecord[] serviceRecord) {
DataElement nameElement = null;
String name = null;
RemoteDevice dev = serviceRecord[0].getHostDevice();
/* 
         * Keep the discovered service record in globalRecord so it is
* available to the communication thread.
*/
        globalRecord=serviceRecord[0];
    }
/* Command handler */
public void commandAction(Command c,Displayable d) {
if (c == exitCommand) destroyApp(true);
else if(c == searchCommand) {
            startInquiry();
}
else if(c == backCommand) {
            switch(currentMenu) {
                
case 11:
case 2:
                    mainMenu(null);
break;
                case 3:
deviceScreen(null);
break;
case 31:    
case 4:
                    selectDataScreen(null);
break;
      
            }
        }else if(c == cancelCommand){
switch(currentMenu) {
case 2: // Device discovery in progress
if (agent.cancelInquiry(this)) {
inquiring = false;
         deviceScreen(null);
}else{
deviceScreen(new Alert("Error",
"Could not stop inquiry or inquiry not started",
null, AlertType.ERROR));
inquiring = false;
}
break;
case 3: //Service discovery in progress
if(!agent.cancelServiceSearch(serviceSearch)) {
selectDataScreen(new Alert("Error",
"No active service search",null,
AlertType.ERROR));
}
break;
}
}else if(c == settingsCommand){
settingsScreen();
}else if (c == btInfoCommand){
BluetoothInfoCanvas canv = new BluetoothInfoCanvas();
canv.addCommand(backCommand);
canv.setCommandListener(this);
display.setCurrent(canv);
currentMenu = 11;
}
else if (c == List.SELECT_COMMAND) {
List list = (List) display.getCurrent();
int index = list.getSelectedIndex();
switch (currentMenu) {
case 1: // Main list of known devices
case 2: //List of newly found devices
if (! deviceVector.isEmpty())
startServiceDiscovery( (RemoteDevice)
deviceVector.elementAt(index));
break;
                case 3: //Browse service
doTransfer(index);
break;
case 31: //Settings changed
switch(index){
case 0:
authenticate = !authenticate;
if(!authenticate) encrypt = false;
break;
case 1:
encrypt = !encrypt;
if(encrypt) authenticate=true;
break;
case 2:
master = !master;
break;
}
settingsScreen();
break;
            }//End switch for list-index
        }// End if for List-command
    }//End commandaction
/* Code executed by the communication thread */
public void run() {
/* Generate connection URL based on user selections */
String conURL = null; 
if(encrypt){
conURL = globalRecord.getConnectionURL(
ServiceRecord.AUTHENTICATE_ENCRYPT,master);
}else if (authenticate){
conURL = globalRecord.getConnectionURL(
ServiceRecord.AUTHENTICATE_NOENCRYPT,master);
}else{
conURL = globalRecord.getConnectionURL(
ServiceRecord.NOAUTHENTICATE_NOENCRYPT,master);
}
StreamConnection conn = null;
Alert a = new Alert("Error",conURL,null,AlertType.ERROR);
a.setTimeout(Alert.FOREVER);
/* Connect to the Benchmark server */
try {
 conn = (StreamConnection) Connector.open(conURL);
} catch (IOException e) {
a.setString("Error creating connection\n URL used:\n"+conURL);
deviceScreen(a);
cleanUp();
return;
}
/* Display information about the server */
StatusCanvas s = new StatusCanvas();
RemoteDevice dev = globalRecord.getHostDevice();
String name = "Unknown";
try {
name = dev.getFriendlyName(false);
} catch (IOException e4) {
name = "Unretrievable";
}
s.connectedToServer(name,dev.getBluetoothAddress(),
dev.isAuthenticated(),dev.isEncrypted());
display.setCurrent(s);
/* Open streams */
try {
out = conn.openDataOutputStream();
in = conn.openInputStream();
} catch (IOException e1) {
a.setString("Error opening streams");
display.setCurrent(a,serviceList);
cleanUp();
return;
}
/* Write the number of iterations */
byte[] bytes = new byte[512];
try {
out.writeInt(iterations);
out.flush();
} catch (IOException e2) {
a.setString("Error doing first write");
display.setCurrent(a,serviceList);
cleanUp();
return;
}
/* Send the actual data */
try {
for (int i = iterations; i > 0; i--){
out.write(bytes);
out.flush();
in.read();
}
} catch (IOException e3) {
a.setString("Error writing main load");
display.setCurrent(a,serviceList);
cleanUp();
return;
}
/* Clean up streams and connection */
cleanUp();
/* Display the number of KB sent */
a.setString("Sent " + iterations/2 + " KB. All well!");
a.setType(AlertType.INFO);
a.setTitle("Done!");
deviceScreen(a);
}
/* Close streams and streamconnection */
private void cleanUp(){
try {
if (out != null){
out.close();
}
if (in != null){
in.close();
}
if(conn != null){
conn.close();
}
} catch (IOException e) {
// Error occurred
}
}
}