Care must be taken when developing Bluetooth MIDlets. A Java/Bluetooth implementation is cutting edge technology and has its flaws. During development of my sample Bluetooth MIDlets I found out that not everything works as expected. These tips apply to the Nokia 6600 and Sony Ericsson P900 smartphones.
When a RFCOMM link is set up and ready to use it is expected that one should be able to send some data from
one device to another and shut down the link without problems. It turns out that the link is shut down, possibly
before the data is transfered. Hence, one way communication is not reliable over RFCOMM links. Nasty exceptions is thrown,
like the "Symbian error = - 36" exception. I discovered this when developing my benchmark program, where I
set up a link, transfered some data from device A to device B and then shut down the link.
The solution to this problem is to transfer some amount of data from device A to device B and then send a byte back
from device B to device A before shutting down the link. Note that you must flush your connection in order to send your
data.
Care must also be taken concerning the amount of data sent in one go. It seems one of the buffers in use in the 6600 and P900
smartphones is 512 bytes. When trying to transfer more than 512 bytes in one go, the receiver gets 512 bytes then the
connection freezes up. Sending 512 bytes, flushing, sending 1 byte back, flushing works fine. You can then keep your
connection going.
All streams have an end, they say. This is also the case for Bluetooth links. When using an InputStream
obtained from the StreamConnection object you should get -1 when there is no more data in the stream.
In the real world, this is not the case. You get an exception, once again the "Symbian error = - 36" exception.
I worked around this by first of all sending the number of bytes I would transfer. I then sent my bytes. The other device would
then know how much data it could expect and stop reading when all data was received, thus avoiding the exception.
Doing this is fairly easy, since a DataInputStream and DataOutputStream can be obtained from the
StreamConnection. Simply send an int with the number of bytes you intend to transfer.
Service records are added to the Bluetooth Service Discovery Database (SDDB) when you call the acceptAndOpen() on the
StreamConnectionNotifier object. This is a blocking operation and should therefore be done in a seperate thread.
To remove the Service record from the Bluetooth SDDB one must call the close() method on the
StreamConnectionNotifier. This is very important. If your MIDlet exits without doing this, the service record will
stay in the Bluetooth SDDB, despite the fact that your MIDlet is dead. This may or may not have security implications, I have not
investigated just how much damage one can do with a dangling service record.
The ServiceRecord class provides a populateRecord() method. This method should make the device go on
air to retrieve the attributes supplied as parameter from the remote device's service record. I tested this method, it returned false
every time, indicating that it could not retreive any attributes. This did not make sense since the device was able to retrieve the same
attributes during the initial service search. The conclusion is: retrieve the attributes you want in the initial service search.
The populateRecord() method does not work as expected.
The P900 discovers all nearby devices but the inquiryCompleted() method is always called with INQUIRY_ERROR
as parameter when the inquiry completes normally. A possible explanation is that Sony Ericsson has swapped the INQUIRY_ERROR and
INQUIRY_COMPLETED values. I have not been able to test this, I do not know how to force an error during inquiry.
This page was last updated 14. Jul. 2006
Comments and feedback are highly appreciated.
You can reach me at: klings (at) nowires (dot) org