jsr 82 works fine on emulator, but not on real device

Hi,
I am currently working on a project, where i am using the bluetooth jsr 82 lib.
On the emulator the device discovery and service discovery are working
-> the dicsovered service are listed on the display
-> i can choose a server
-> and connect to it.
Like the topic says its working on the emulator but not on the phones i tested (k750, v610i, another k750i and a other sony ericsson i think k600… something like that) .

I dont not know where to find the error, i checked the jad file… and the manifest file, which includes this entries:

Manifest-Version: 1.0
MicroEdition-Configuration: CLDC-1.1
MIDlet-Name: TestforMIDlet Suite
MIDlet-Permissions: javax.microedition.io.Connector.bluetooth.client,j
avax.microedition.io.Connector.bluetooth.server
MIDlet-Vendor: Midlet Suite Vendor
MIDlet-1: StartMIDlet,StartMIDlet
MIDlet-Version: 1.0.0
MicroEdition-Profile: MIDP-2.0

is the linebreak a problem?

I installed the BluetoothDemo from wtk2 on my k750i and on my roommates v610i … it works… moreless the same code like mine, some other variables names etc…

i am using eclipse me for developing, are there any known problems with that IDE ?

please help, if you need any more informations, ask me I am going to post them here.

with best regards

1st rule of working with j2me: emulators suck
2nd rule of working with j2me: emulators lie
3rd rule of working with j2me: only define it as working/broke if you have tried it on a mobile.

that said your questions:
Q: is the linebreak a problem?
A: dunno but avoid that! Also make sure you have an extra line at the bottom or else many devices will have issues

This is definetly a no-go:
MIDlet-Version: 1.0.0
change to 1.0

Q: i am using eclipse me for developing, are there any known problems with that IDE ?
A: not that I know of. I use it for really basic developtment. Are you building with the correct libraries?

my questions:
Are you getting pop-ups asking for permissions?

Can you upload your source and the demo source somewhere so I can look at them?
I am really terrible at citing stuff from the hip.

Yes i get the Popup when i am starting a server (asking to allow creating bt server)
I am using the Sony Ericsson SDK 2.2.4 libaries

this is the source for client:

package network;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.util.Vector;

import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;

import controller.GameController;
import controller.NetworkController;

public class Client implements Runnable, DiscoveryListener{
	
	
	/**save the discoveres Devices*/
	Vector remoteDevices = new Vector();
	
   
    /** Describes this server */
    private static final UUID VERSUS_SERVER_UUID = 
        new UUID("F0E0D0C0B0A000908070605040302010", false);
	
	/** Optimization: keeps service search patern. */
    private UUID[] uuidSet;
	 
	//UUID[] uuidSet = {new UUID(0x0003) };
	int[] attributes = {0x0100, 0x0101, 0x0003, 0x0004, 0x0000};
	
	Thread clientThread;

	
	LocalDevice localDevice;
	DiscoveryAgent discoveryAgent;
	
	boolean testBT;

    /** Keeps the device discovery return code. */
    private int discType;
	
	
    /**
     * Connection spezified stuff
     */
	String connectionURL;
	
	/** connection*/
	StreamConnection connection;
	
	/**write*/
	OutputStream os;
	
	/**read*/
	InputStream is;
	
	ClientReceiverThread receiver;
	boolean connected = false;
	
	
	
	public Client(){
		receiver = new ClientReceiverThread();
	}
	
	
	
	public void start(){
		NetworkController.getInstance().setClientBusy(true);
		clientThread = new Thread( this );
		clientThread.start();
	}
	
	
	
	public void run(){
		
		try{
			
			 // initialize bluetooth first
	     
			
			// create/get a local device and discovery agent
			localDevice = LocalDevice.getLocalDevice();
			discoveryAgent = localDevice.getDiscoveryAgent();
			
			 // remember we've reached this point.
    
            
		}catch(BluetoothStateException e){}
		
		//initialize some optional variables
		uuidSet = new UUID[2];
		  // ok, we are interesting in btspp services only
	    uuidSet[0] = new UUID(0x1101);

	    // and only known ones, that allows pictures
	    uuidSet[1] = VERSUS_SERVER_UUID;
		
		
	    remoteDevices.removeAllElements();
	    //Ok now we can search for Devices..
	
	    searchDevices();
	
	   if(remoteDevices.size() > 0){
		   
	    	searchServices();
	   }else {
	    	System.out.println("no Device found");
	   }
	    
	 try{ 
		 // notified by notifyConnection() when trying to connect to Server..
		   synchronized(this){
			   wait();
		   }
		 
	   } catch(InterruptedException e){
		   
	   }
		connectionURL = (String)NetworkController.getInstance().getRemoteConnectionURLs().firstElement();
		System.out.println("url: "+connectionURL.toString());
		enterConnection(connectionURL);
	}

	public void searchDevices() {
	
		try {
	   
	    	
	   
			// To start searching for Bluetooth-enabled phones, use the DiscoveryAgent
			discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
			System.out.println("searching for Devices...");
		} catch (BluetoothStateException e) {
			e.printStackTrace();
		}
		
		 try {
			 synchronized(this){
			 // until devices are found
	         wait(); 
			 }
	         
	        } catch (InterruptedException e) {
	            System.err.println("Unexpected interuption: " + e);
	        }
	        
	        System.out.println("search Device komplett");

	}
	
	
    /**
     * Invoked by system when a new remote device is found -
     * remember the found device.
     */
	public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass cod) {
		System.out.println("device discoverd...");
		try {
			
			remoteDevices.addElement(remoteDevice);
		
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	
	/**
     * Invoked by system when device discovery is done.
     * <p>
     * Use a trick here - just remember the discType
     * and process its evaluation in another thread.
     */
    public void inquiryCompleted(int discType) {
        this.discType = discType;
     
        synchronized(this){
            notify();
            System.out.println("search Device notify");
        }
    }
    
    public void searchServices(){
    	try {
	
			for ( int i = 0; i < remoteDevices.size(); i++) {
				discoveryAgent.searchServices(attributes, uuidSet,
						(RemoteDevice) remoteDevices.elementAt(i), this);
			}
			
		} catch (BluetoothStateException e) {
			e.printStackTrace();
		}
    }
    
    
    public void servicesDiscovered(int transID, ServiceRecord[] serviceRecord) {
		try {

			/*
			 * Wenn das Versus aktiv ist versendet bluetooth die Versus ID:
			 * vssrvnm dadurch werden nur entsprächende ServiceRecords
			 * gefiltert, die auf die man zugreifen soll
			 */
		
			// TODO:else anweisung für DEBUG nachher rausnehmen
			if (serviceRecord[0].getAttributeValue(0x100).getValue().toString()
					.equals("vssrvnm")) {
				/*
				 * Gefundene Versus Services werden dem Networkcontroller
				 * übergeben.
				 */
				System.out.println("Versus Server gefunden...");
			
				NetworkController.getInstance().addServiceRecords(serviceRecord[0]);
				NetworkController.getInstance().setServiceDiscovered(true);
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
	public void serviceSearchCompleted(int arg0, int arg1) {
		// TODO Auto-generated method stub
		NetworkController.getInstance().setClientBusy(false);
		NetworkController.getInstance().updateServerList();
		NetworkController.getInstance().drawServerList();
		System.out.println("service search completed: list updated...");

	}

	
	public void enterConnection(String URL){
		
		
		
		try {
//			 open a connection to the server
			connection = (StreamConnection)Connector.open(URL);
			System.out.println(connection.toString());
		 } catch (IOException e) {
             System.err.println("Note: can't connect to: " + URL);
		 }
		 try{
			connected = true;
			//			 Send/receive data
			byte[]buffer = new byte[100];
			System.out.println("bevore method receive bytes client");
			
			
			receiver.start(connection);
			os = connection.openOutputStream();
		
		    String msg = "1hello there";
		  //  InputStream is = connection.openInputStream();
		  
		    
		     
		    // send data to the server
		    os.write(msg.getBytes());
		    
		    // read data from the server
		
		    /*
		     *     is.read(buffer);
		
		   	String text = new String(buffer);
  			System.out.println(text);
		     */
		
	   	 
		    	/*
			    * Here is where the game starts
			    */
	        
	        
		    
	        
	        //closeConnection();
	        
		} catch(Exception e) {
		  e.printStackTrace(); 
		}
		
	}
	
	public void sendCommand(int i){
		try{
			os.write(i);
		}catch(IOException e){
			
		}
	}
	
	public void sendCommand(byte[] b){
		try{
			os.write(b);
		}catch(IOException e){
			
		}
	}
	/*
	 * falls man die funktion als thread laufen lassen kann receiveBytes verwenden anstatt classe receiver
	 */
	public void receiveBytes(StreamConnection connection){
			
		  byte buffer[] = new byte[100];
		try{
			
			InputStream is = connection.openInputStream();
			while(connected){
				is.read(buffer);
				NetworkController.getInstance().ceh.handleIncomingBytes(buffer);
				System.out.println("received");
			}
		}catch(IOException e){
			e.printStackTrace();
		}
		
	}
	
	public void closeConnection(){
		try{
			connected = false;
			 connection.close();
		}catch(IOException ioe){
		
				
		}
	}



	public LocalDevice getLocalDevice() {
		return localDevice;
	}
	
	public void notifyConnection(){
		synchronized(this){
			notify();
		}
	}

}


/**
 * 
 * @author Admin
 *	ClientReceiverThread: Class for listening to incoming Events
 */

class ClientReceiverThread implements Runnable{
	boolean connected;
	StreamConnection connection;

	public ClientReceiverThread(){}
	
public void start(StreamConnection c) {
	this.connection = c;
	this.connected = true;
	Thread t = new Thread(this);
	t.start();
}

public void run() {
	try {
		InputStream is = connection.openInputStream();
		byte[]buffer = new byte[100];
		
		while (connected) {
			is.read(buffer);
			NetworkController.getInstance().ceh.handleIncomingBytes(buffer);
			}
		
		
	} catch (IOException ioe) {

	}

}
}

this for the server:

package network;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;

import javax.bluetooth.DataElement;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connection;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;

import controller.GameController;
import controller.NetworkController;


public class Server implements Runnable{
	
	
    private LocalDevice localDevice;
	
	ServiceRecord serviceRecord;
	StreamConnection connection;
	OutputStream os;
	
	/** Describes this server */
    private static final UUID VERSUS_SERVER_UUID = 
        new UUID("F0E0D0C0B0A000908070605040302010", false);

	
	 
	boolean connected = false;
	ServerReceiverThread receiver;
	
	public Server(){
		receiver = new ServerReceiverThread();
	}
	
	public void start(){
		Thread t = new Thread( this );
       // this.activeThread = t;
		t.start();
      
	}
	
	public void cancel(){
	
		Thread t = new Thread(this);
		try{
			t.sleep(1000);
			t.interrupt();
			System.out.println("server active: "+ t.isAlive());
		}catch(Exception e){
			e.printStackTrace();
		}
	
		//System.out.println(activeThread.isAlive());
	}

	
	public void run(){
		 try{
        localDevice = LocalDevice.getLocalDevice();
       
        // set we are discoverable
        if (!localDevice.setDiscoverable(DiscoveryAgent.GIAC)) {
	          System.out.println("not discoverable");
        }
	   } catch (Exception e) {
           System.err.println("Can't initialize bluetooth: " + e);
       }
	   
	   StringBuffer url = new StringBuffer("btspp://");
		//createService();
		 // indicate this is a server
        url.append("localhost").append(':');

        // add the UUID to identify this service
        url.append(VERSUS_SERVER_UUID.toString());

        // add the name for our service
        url.append(";name=Versus Server");

        // request all of the client not to be authorized
        // some devices fail on authorize=true
        url.append(";authorize=false");
  
		createConnection(url.toString());
	}


	public void createConnection(String url){
		try{
		   StreamConnectionNotifier notifier =
		       (StreamConnectionNotifier) Connector.open(url.toString());
		  
		    serviceRecord = localDevice.getRecord(notifier);
		
		    serviceRecord.setAttributeValue(0x0100, new DataElement(DataElement.STRING, "vssrvnm"));
		    serviceRecord.setAttributeValue(0x0101, new DataElement(DataElement.STRING, "test"));
		
		   localDevice.updateRecord(serviceRecord);
	
		  // getBTProperties();
		    // accept client connections
		   
		    connection = notifier.acceptAndOpen();
			
		    
		    localDevice.setDiscoverable(DiscoveryAgent.NOT_DISCOVERABLE);
		    receiver.start(connection);
		    connected = true;
		    os = connection.openOutputStream();
		    
		    String msg = "1hello there Client";
		  //  os.write(msg.getBytes());
		        /*
				 * Here is where the gaming starts
				 */
	
		    startNetworkGame();
		  // 	 connection.close();
	
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	
	public void closeConnection(){
		try{
			connected = false;
			 connection.close();
		
		}catch(IOException ioe){
			
		}
	   
	}
	
	
	public void startNetworkGame(){
		sendCommand(GameController.getInstance().STARTGAME);
		GameController.getInstance().startGame();
	}
	
	
	public void sendCommand(int i){
		try{
			os.write(i);
		}catch(IOException e){}
			System.out.println("da geht was nicht");
		}
		
	public void sendCommand(byte[] b){
		try{
			os.write(b);
		}catch(IOException e){}
	}
	
	

	public void getBTProperties(){
		System.out.println(NetworkController.getInstance().getConnectionManager().getLocalDevice().getProperty("bluetooth.api.version"));
		System.out.println(NetworkController.getInstance().getConnectionManager().getLocalDevice().getProperty("bluetooth.sd.attr.retrievable.max"));
		System.out.println(NetworkController.getInstance().getConnectionManager().getLocalDevice().getProperty("bluetooth.connected.devices.max"));
		System.out.println(NetworkController.getInstance().getConnectionManager().getLocalDevice().getProperty("bluetooth.connected.inquiry.scan"));
		System.out.println(NetworkController.getInstance().getConnectionManager().getLocalDevice().getProperty("bluetooth.api.version"));
		System.out.println(NetworkController.getInstance().getConnectionManager().getLocalDevice().getProperty("bluetooth.connected.inquiry"));
	}
	

}

class ServerReceiverThread implements Runnable{
		boolean connected;
		StreamConnection connection;
	
		public ServerReceiverThread(){}
		
	public void start(StreamConnection c) {
		this.connection = c;
		this.connected = true;
		Thread t = new Thread(this);
		t.start();
	}

	public void run() {
		try {
			InputStream is = connection.openInputStream();
			byte[]buffer = new byte[100];
			
			while (connected) {
				is.read(buffer);
				NetworkController.getInstance().seh.handleIncomingBytes(buffer);
				}
			
			
		} catch (IOException ioe) {

		}

	}
	

	
}

Been a while since I last worked with BlueTooth.

nggff, example code.
Sometimes good, sometimes bad… having a thread wait for another? Maybe not the best thing.

One thing I did notice is that in the following line you only try to catch IOException

connection = (StreamConnection)Connector.open(URL);

It is VERY important, when working with MIDP, to read the documentation. Then you might have seen this:


    IllegalArgumentException - If a parameter is invalid.
    ConnectionNotFoundException - if the requested connection cannot be make, or the protocol type does not exist.
    IOException - If some other kind of I/O error occurs.

ALLWAYS catch Exception

There are many instances where the method only will require one Exception to be caught but also throws a few others.

InputStream.readFully() is another example where besides throwing IOException it can also throw a EOFException.

Don’t worry, it is a common oversight.

Also I noticed that you open connections and never close them.
On mobiles it is imperative that you clean up after yourself. Some do not close them.

Eh ghad my memory is bad but iirc you can just open one input- and one outputstream per connection and just keep them open.
Create a thread each and for the input, use the blocking call read().

Ok i am going to fix that, but i think that is not the problem, because the programm is not running till this “codeline” … because the Service Record or the Device (or both) of the Server is not found by the client… that suxx… :stuck_out_tongue:

The device is not found? I thought it was, my bad.

Could it be a thread issue? Having one wait for the other might not be the best thing.

If you are working on a game have the canvas have its own canvas so it can repaint itself via the main class.
Then run the detection run in it’s own thread and write info to a vector.
The main class can then paint the info of that vector.

You really need some way to debug your code. Since that is not possible on the phones I would do either/or:
write all debug info to a file using the fileconnection api.
and if your midlet can support it, write the debug stuff to a vector and then display them on the screen/debug overlay.
(the third option would be sending the debug info to the pc via bluetooth, that is naturally not an option :wink: )

Also get the document from jcp.org. It, among others, shows that you can have a server running on the same device. This might help and save you a second device for testing.

The Server (or Client) and the Canvas are independent…
I just adding a debug mode to the programm ;D

thx for the hint on jcp.org, i will try that now.
thx so far

All the SE phones you listed support on-device debugging. (and infact the device supports more debugger features than the crappy wtk emulators!)

There is a guide available on eclipseMe.org that describes how to set it up.

What I ment was to make sure no thread it waiting for another to execute.

True, but… works for SE and some Nokias as well. After that, who knows?

If this is a school project to be forgotten in a month, then such an on-device-debugging is great.

But if you (meaning him) intend to go mainstream, you will need something that will work on all devices at all times.
Debug point 2 is the ugliest but will work nearly everywhere, is foolproof and does not require setting up.
With some added features it can become quite handy.

I just prefer simple solutions that not only introduces the developer to the evil world of mobile debugging hell but also won’t have them comming back complaining that device XY does not have on device debugging. (like my currently beloved N73, DIE FIEND!)

Hehe, i cant find the Article on jpc.org, do you meen the bluetooth specifications?

I should use the device debuggin mode, i think it can help

yes the specifications as the doc also contains example code.

Hi,
i just tested the game, and it is running,
i dont know why… i added a debug mode… i changed midlet 1.0.0 to 1.0
and i added ja other jsr82 jar… hmm
yuhuuu

thx for helping !

You should make a greater distinction between debugging (attaching a debugger to the VM), and logging (recording execution progress).

Debugger support is available on almost all SonyEricsson, Motorola and some Nokia handsets.

Logging on the otherhand can be done on any handset, in all kinds of imaginative ways.
Some handsets provide limited logging support at the VM level by redirecting standard out & err streams (System.[out/err]) to a file or serial connector.
Otherwise logging can be done at the application level, you can direct the logging output to what ever output the handset supports.
screen, file, rms, cable serial / bluetooth / IR serial ports, net port, http post, sms etc.

There is also atleast one project that, via bytecode engineering, aims to offer some of the functionality of a VM debugger, but at the application level.
I havn’t tried it out myself, but I can imagine it has such massive overheads on the speed & memory consumption of the application that for typical porting work it is impractical.