The Bluetooth protocol stack lets you use several methods, including RFCOMM and Object Exchange (OBEX), to send and receive files between devices. RFCOMM is better when you want to send and receive stream data (and when you'd like to take a traditional serial port application and Bluetooth-enable it). On the other hand, OBEX is great when you want to send object data, context, and metadata about the payload. In this article, you become familiar with the Java language library used to control a Bluetooth device and learn how JSR-82 API and OBEX can be used to transfer files between the client and server.
Bluetooth is the wireless protocol of choice for several mobile device manufacturers and has several attractive features, most importantly, its low-power consumption for data transmissions. As of June 2004, more than five million Bluetooth-enabled devices ship each week, providing a high penetration rate in the consumer electronics market for the technology.
The Bluetooth protocol in review
There are three versions of the Bluetooth protocol running in devices currently on the market -- Version 1.1, 1.2 AFH, and 2.0+EDR. This doesn't pose a problem to developers and users because the newer versions of the protocol are compatible with the previous versions. Table 1 shows some of the similarities and differences in the currently available Bluetooth versions.
Table 1. Bluetooth protocol versions
| Version | Raw data rate | Communication range (feet) | Notes |
|---|---|---|---|
| Bluetooth 1.1 | 1 Mbps | 30-300 | The most commonly deployed Bluetooth version on the market. |
| Bluetooth 1.2 AFH | 1 Mbps | 30-300 | Includes Advanced Frequency Hopping technology to better co-exist with WiFi networks. |
| Bluetooth 2.0+EDR | 3 Mbps | 30-300 | Includes Enhanced Data Rate technology to transmit data at higher speeds. |
Now let's review the firmware/software that controls the Bluetooth device: the stack.
What's the purpose of the Bluetooth stack? The stack is the piece of software (and firmware) that controls your Bluetooth device. Figure 1 details the protocol stack.
Figure 1. The Bluetooth protocol stack

- The bottom layer of the stack is the HCI, the Host Controller Interface. This layer is literally the interface between the host (your computer) and the controller (the Bluetooth device). As you can see, all other layers go through the HCI.
- The layer above the HCI is L2CAP, the Logical Link Controller Adaptation Protocol. This layer acts as the data multiplexer for all other layers.
- The next layer is BNEP, the Bluetooth Network Encapsulation Protocol. Using BNEP, you can run other networking protocols, such as IP, TCP, and UDP, over Bluetooth.
- RFCOMM is known as the virtual serial port protocol because it allows a Bluetooth device to simulate the functions of a serial port.
- The OBEX protocol layer is implemented above the RFCOMM layer and is useful when you want to transfer data as an object, such as files.
- SDP is the Service Discovery Protocol layer, which is used whenever you want to find services on a remote Bluetooth device.
- The final two layers, AVCTP and AVDTP are used for the control and distribution of audio and video over Bluetooth. AVCTP and AVDTP are relatively new additions to the Bluetooth protocol; they are used when you want to control the functions of a media player or if you want stream audio in stereo.
Sending files: RFCOMM or OBEX?
Let's take a look at two simple protocols in the stack used to send data, RFCOMM and OBEX, and compare the advantages and disadvantages of using them when transferring files.
You can use RFCOMM or OBEX to send and receive files between Bluetooth devices. However, RFCOMM is the better choice when you want to send and receive stream data, just like you would with a traditional serial port. In the real world, RFCOMM should be used when you want to take a traditional serial port application and make it Bluetooth-enabled. If you're sending simple text strings between two Bluetooth devices (as in a chat application), then there may not be much of an advantage to using OBEX. In this case, you should probably use RFCOMM or L2CAP.
On the other hand, OBEX is great when you want to send object data such as files. Using OBEX, you can send not only data, but you can also send context or metadata about the payload. For instance, when sending a file using OBEX, you are also able to send other useful information about the file such as the file name, file type, file size, or anything else that you want to describe the file.
So now that I've decided to use OBEX to send object-data files using Bluetooth, let's take a look at the official library that allows you to control a Bluetooth device using the Java language.
The JSR-82 is the official Java API for Bluetooth wireless technology. Using this API you can create applications that perform any of the following functions:
- Determine and inspect the properties of your own Bluetooth device
- Discover Bluetooth devices within the communication range of your device
- Search for services on remote Bluetooth devices
- Create Bluetooth client applications that can communicate with remote Bluetooth servers
- Create Bluetooth server applications that can service requests from Bluetooth clients
The JSR-82 consists of two packages, javax.bluetooth and javax.obex. Your own Bluetooth device is represented by the javax.bluetooth.LocalDevice class and all remote Bluetooth devices are represented by the javax.bluetooth.RemoteDevice class.
The javax.bluetooth.DiscoveryAgent class is a helpful class that allows you to discover remote Bluetooth devices in the vicinity and returns a javax.bluetooth.RemoteDevice for each Bluetooth device in the area. You can also use javax.bluetooth.DiscoveryAgent to search for services in the remote devices that you've found.
If you want to be notified when discovery events occur, you'll need to implement the methods of the javax.bluetooth.DiscoveryListener interface. That all sounds pretty simple, right? Well, the level of complexity increases a bit, however, when you want to create OBEX applications.
Just in case you didn't know, OBEX is not a native protocol of Bluetooth, but was actually created by the designers of Infrared Data Association. Because OBEX is an adopted protocol, the authors of the Java Bluetooth API decided to create a separate package for OBEX applications; this way, you can use Java language to create OBEX applications to work over any transport (such as infrared or TCP/IP) and not just through Bluetooth.
When you create OBEX applications using the Java Bluetooth API, you're going to use some of the classes and interfaces in the javax.obex package. As I stated earlier, the OBEX layer in the Bluetooth protocol stack is really geared toward file transfers between Bluetooth devices, so just like with the traditional FTP, OBEX applications have operations such as GET and PUT.
What is an OBEX operation, anyway?
When clients and servers communicate within an OBEX session, their interactions are called operations. For each operation sent from a client, the server gives a response that indicates the status of the operation. To get a clear picture of how operations and responses work for OBEX clients and servers, take a look at Figure 2:
Figure 2. OBEX operations and response codes

What does it take to send a file from a phone to a printer, as depicted in Figure 2? First of all, before you create the OBEX session, a transport connection needs be established (Bluetooth, infrared, TCP/IP, and so on). Because this article is about Bluetooth, there should be no surprise as to which underlying transport I'm going to use.
After the transport connection has been established, the Bluetooth client needs to issue the CONNECT operation. If the Bluetooth server, in this case, the printer, wanted to accept a new client to use its service (like the printing service), then it will respond to the client with the response code for success, 160. If the printer didn't want to accept any new clients, then it would respond with a response code of 211, the response code for "OBEX SERVICE UNAVAILABLE."
Now let's assume that the printer has accepted the CONNECT operation. I have now created an OBEX session between the client and the server. With the OBEX session now in place, I am able to send requests (please note that requests and operations are synonymous) to the OBEX server. Of course, the GET and PUT operations are self-explanatory. The SETPATH operation, however, is primarily used when the OBEX server has a filesystem. An OBEX client will send a SETPATH request to instruct the OBEX client to change the working directory (the cd command). The SETPATH operation is usually followed by a GET or PUT operation. To terminate the OBEX session, the client needs to send the DISCONNECT operation. If successful, the OBEX server will respond with the success response code 160.
Now that you have a good understanding of the semantics of OBEX, let's take a look at how the Java language, Bluetooth, and OBEX are all put together in the JSR-82 API. I'll start in with the server code first, because the client code will be more complex.
Creating an OBEX server application
My server application is called FileServer.java and because "first things are first," let's take a look at the import statements and class declaration in Listing 1.
Listing 1. Import statement and class declaration
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.microedition.io.*;
import java.io.*;
import javax.bluetooth.*;
import javax.obex.*;
public class FileServer extends ServerRequestHandler
implements ActionListener{
|
If you want to create an OBEX server, you need to extend the javax.obex.ServerRequestHandler class. Because this example is a Java 2 Platform, Standard Edition (J2SE) application, I also want to implement the interface ActionListener so that I can respond to button clicks. When the users click on the button to start the server, the actionPerformed() is called (which is shown in Listing 2).
Listing 2. FilesServer.actionPerformed()
public void actionPerformed(ActionEvent e) {
startButton.setEnabled(false);
try {
UUID uuid = new UUID("8841", true);
String url = "btgoep://localhost:" + uuid
+ ";name=FTP;authenticate=false;master=false;encrypt=false";
SessionNotifier sn = (SessionNotifier)Connector.open(url);
updateStatus("[server:] Now waiting for a client to connect");
sn.acceptAndOpen(this);
updateStatus("[server:] A client is now connected");
} catch (Exception ex){
}
}
|
Each Bluetooth service on a machine needs a unique identifier, so I decided to give this service the UUID (Universal Unique Identifier) of 8841 (it could be any four-digit number you choose). You're going to need to remember the UUID when you create the client application.
Because I'm creating a JSR-82 server application, I need to call Connector.open() and pass in a String that contains the URL for the service. Because this is an OBEX application, the protocol that I'm using is btgoep. Also, you can also see that the service is named "FTP" (although, it could be named anything).
FileServer.java is an OBEX server application, so that means that OBEX clients will be sending OBEX operations such as CONNECT, GET, PUT, and so on. Therefore, the class needs to properly handle each operation that the client will send (or rather, the operations that I want to handle). For that reason, in
FileServer.java, I've included implementations for methods onPut(), onConnect(), and onDisconnect(). I could have created an implementation for onGet(), but because I just want to send a simple file from the client to the server, implementing the onGet() isn't needed, just the onPut() method.
Listing 3 demonstrates the code onConnect() and onDisconnect(). As you can see, onConnect() requires an int as a return value, but onDisconnect() doesn't return anything at all because it's not needed.
Listing 3. FilesServer.onConnect() and FilesServer.onDisconnect()
public int onConnect(HeaderSet request, HeaderSet reply) {
updateStatus("[server:] The client has created an OBEX session");
return ResponseCodes.OBEX_HTTP_OK;
}
public void onDisconnect (HeaderSet req, HeaderSet resp) {
updateStatus("[server:] The client has disconnected the OBEX session");
}
|
Now let's take a look at the piece of code that allows FileServer.java to accept a file from a client when the client sends a PUT request. The code for onPut() is shown in Listing 4.
Listing 4. FilesServer.onPut()
public int onPut (Operation op) {
try {
java.io.InputStream is = op.openInputStream();
updateStatus("Got data bytes " + is.available() + " name "
+ op.getReceivedHeaders().getHeader(HeaderSet.NAME) +
" type " + op.getType());
File f =
new File((String)op.getReceivedHeaders().getHeader(HeaderSet.NAME));
FileOutputStream fos = new FileOutputStream (f);
byte b[] = new byte[1000];
int len;
while (is.available() > 0 && (len = is.read(b)) > 0) {
fos.write (b, 0, len);
}
fos.close();
updateStatus("[server:] Wrote data to " + f.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
return ResponseCodes.OBEX_HTTP_OK;
}
|
As I said earlier, the code in Listing 4 shows how the OBEX server will accept a file from a remote Bluetooth device. You may notice that the file name of the transferred file can be obtained and, in this case, the file name is used when instantiating the File object.
In this article, I've covered a lot of ground to get you started creating a Java Bluetooth application that uses the OBEX protocol. You learned when it is best to choose OBEX over RFCOMM for data transfer. You should also walk away from this article with solid knowledge regarding the semantics required for any OBEX application.
In Part 2 of this series, I'll show you how to create a client application that properly communicates with the server that I have just created. After you have a solid understanding of the client code, I'll make a few modifications to the client code in order to create the Bluetooth Music Store.
-
The examples in this article were created using the JB-22 Java Bluetooth Development kit. The JB-22 is a complete Java Bluetooth development kit featuring both Bluetooth hardware and software.
-
Bluetooth specifications can be obtained at the Bluetooth SIG Web site.
-
The "PalmOS data collection series" (developerWorks, November 2001) explores the key ingredients in developing data-collection applications for wireless devices.

Bruce Hopkins is the author of the book, Bluetooth for Java (Apress) and is the creator of the JB-22 developer kit. He graduated from Wayne State University in Detroit with a B.S. degree in Electrical and Computer Engineering. He currently works as a Technical Architect for Gestalt LLC and focuses on distributed computing, Web services, and wireless technologies. He can be contacted at bhopkins@gestalt-llc.com.





