HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML

This article is the second installment in a two-part series on Java and Bluetooth. Last month you got your feet wet in Bluetooth (JDJ, Vol. 7, issue 8); if you don't remember what the role of a Bluetooth stack or a Bluetooth profile is in the context of a Bluetooth application, refer to Part 1.

Let's recap. The basic concepts of any Bluetooth application (Java or otherwise) consist of the following components:

  • Stack initialization
  • Device management
  • Device discovery
  • Service discovery
  • Service registration
  • Communication
We covered stack initialization last month, so let's proceed!

Device Management
LocalDevice and RemoteDevice are the two main classes in the Java Bluetooth Specification that let you perform device management. These classes allow you to request some statistical information about your Bluetooth device (LocalDevice) as well as some information about the devices in the area (RemoteDevice). The static method LocalDevice.getLocalDevice() returns an instantiated LocalDevice object for you to use. To get the unique address of your Bluetooth radio, call getBluetoothAddress() on your local device object. The Bluetooth address serves the same purpose as the MAC address on the network card of your computer; every Bluetooth device has a unique address. If you want other Bluetooth devices in the area to find you, call the setDiscoverable() method in LocalDevice object.

That's about all it takes to perform device management with the Java Bluetooth Specification APIs. Now, let's look at the concept that allows you to discover other Bluetooth devices: device discovery.

Device Discovery
Your Bluetooth device doesn't know what other Bluetooth devices are in the area. Perhaps there are laptops, desktops, printers, mobile phones, or PDAs nearby. Who knows? The possibilities are endless. To find out, your Bluetooth device uses Device Discovery classes that are provided in the Java Bluetooth API to see what else is out there.

The two classes required for your Bluetooth device to discover remote Bluetooth devices in the area are DiscoveryAgent and DiscoveryListener.

After getting a LocalDevice object, instantiate a DiscoveryAgent by calling LocalDevice.getDiscoveryAgent().

LocalDevice localdevice = LocalDevice.getLocalDevice();
DiscoveryAgent discoveryagent = localdevice.getDiscoveryAgent();

The are multiple ways to discover remote Bluetooth devices, but I'll discuss one particular method. First, your object must implement the DiscoveryListener interface. This interface works like any listener, so it'll notify you when an event occurs. In this case, you'll be notified when Bluetooth devices are in the area. To start the discovery process, call the startInquiry() method on your DiscoveryAgent. This method is nonblocking, so you're free to do other things while you wait for other Bluetooth devices to be found.

When a Bluetooth device is found, the JVM calls the deviceDiscovered() method of the class that implemented the DiscoveryListener interface. This method passes you a RemoteDevice object that represents the device discovered by the inquiry.

Service Discovery
Now that you know how to find other Bluetooth devices, it would be nice to see what services they offer. Of course, if the RemoteDevice is a printer, you know it can offer a printing service. But what if the RemoteDevice is a computer? Would it readily come to mind that you can also print to a printer server?

That's where service discovery comes in. You can never be sure what services a RemoteDevice may offer, so service discovery helps you find out.

Service discovery is just like device discovery ­ you use the DiscoveryAgent to do the "discovering." The searchServices() method of the DiscoveryAgent class allows you to search for services on a RemoteDevice. When services are found, the servicesDiscovered() method will be called by the JVM if your object implemented the DiscoveryListener interface. This callback method also passes in a ServiceRecord object that pertains to the service you searched for. With a ServiceRecord in hand, you can do plenty of things, but you would most likely want to connect to the RemoteDevice where this ServiceRecord originated:

String connectionURL = servRecord[i].getConnectionURL(0,false);

Service Registration
Before a Bluetooth client device can use service discovery on a Bluetooth server device, the Bluetooth server needs to register its services internally in the service discovery database (SDDB). This process is called service registration.

Note: In a peer-to-peer application, such as a file transfer or chat application, any device can act as the client or the server, so you'll need to incorporate that functionality (both client and server) into your code in order to handle both scenarios of service discovery (the client) and service registration (the server).

Here's an example of what's involved in getting your service registered and stored in the SDDB (Listing 1 provides the code:

1.   Call Connector.open() and cast the resulting connection to a StreamConnectionNotifier. Connector.open() creates a new ServiceRecord and sets some attributes.

2.   Use the LocalDevice object and the StreamConnectionNotifier to obtain the ServiceRecord that was created by the system.

3.   Add or modify the attributes in the ServiceRecord (optional).

4.   Use the StreamConnectionNotifier and call acceptAndOpen() and wait for Bluetooth clients to discover this service and connect. The system creates a service record in the SDDB.

5.   Wait until a client connects.

6.   When the server is ready to exit, call close() on the StreamConnectionNotifier. The system removes the service record from the SDDB.

StreamConnectionNotifier and Connector come from the javax.microedition.io package of the J2ME platform.

That's all that you need to do service registration in Bluetooth. The next step is communication.

Communication
Okay, Bluetooth is a communication protocol, so how do you communicate with it? Well, the Java Bluetooth API gives you three ways to send and receive data, but for now we'll cover only one of them, RFCOMM. RFCOMM is a the protocol layer that the Serial Port Profile (SPP) uses to communicate, but these two items are almost always used synonymously.

Server Connections with the Serial Port Profile
Listing 2 demonstrates how to open a connection on a Bluetooth device that will act as a server. For the most part, this is the same code used in service registration; service registration and server communication are both accomplished using the same lines of code.

Here are a few items that I want to point out: the string URL begins with btspp://localhost, which is required if you're going to use the Bluetooth Serial Port Profile. Next comes the UUID part of the URL, which is 0011223344556677889900AABBCCDDEEFF. This is simply a custom UUID that I made up for this service; I could have chosen any string that was either 32-bits or 128-bits long. Finally, we have ;name=serialconn in the URL string. I could have left this part off, but I want my custom service to have a name, so the actual service record in the SDDB has the following entry:

ServiceName = serialconn

The implementation also assigned a channel identifier to this service. The client must provide the channel number along with other parameters in order to connect to a server.

Client Connections with the Serial Port Profile
Establishing a connection with the SPP for a J2ME client is simple because the paradigm hasn't changed for J2ME I/O. Simply call Connector.open().

StreamConnection con =
(StreamConnection)Connector.open(url);

Obtain the URL string that you need to connect to the device from the ServiceRecord object you get from service discovery. The following is a more complete demonstration of how an SPP client makes a connection to an SPP server.

String connectionURL =
serviceRecord.getConnectionURL(0,false);
StreamConnection con =
(StreamConnection)Connector.open(connectionURL);

What does an SPP client connection URL look like? If the address of the server is 0001234567AB, the string for the SPP client would look something like this:

btspp://0001234567AB:3

The "3" at the end of the URL string is the channel number that the server assigned to this service when it was added to the SDDB.

Java Bluetooth Development Kits
Who makes this stuff and how can you get your hands on it? Here are your options:

The JSR-82 Reference Implementation was created by Motorola, so they're responsible for distributing it (www.motorola.com/java). Unfortunately, this Reference Implementation is only the JSR-82 APIs (see Figure 1, section B) so you won't be able to do much with it even if you have some Bluetooth hardware. To get the JSR-82 Reference Implementation to work on your development system, you need to license the Motorola CLDC as well.

Figure 1
Figure 1

If you already have Bluetooth devices for your development computers, try out the JSR-82­compliant Java Bluetooth solution from Atinav (www.atinav.com). They support numerous RS-232, UART, USB, CF, and PCMCIA Bluetooth devices. Their solution is based on an all-Java stack and their SDK includes the following profiles: GAP, SDAP, SPP, and GOEP. This solution also includes a KVM, so you only need to obtain the Bluetooth hardware to create and test your apps.

Rococo (www.rococosoft.com) is most famous for their Java Bluetooth simulator, although they also make a Java Bluetooth developer kit for the Palm OS. Using the Impronto Simulator, Java developers only need a single computer to compile and test their Java Bluetooth applications. The simulator supports GAP, SDAP, SPP, and GOEP profiles, and is currently priced at $1,000.

Esmertec (www.esmertec.com) is well known for their Jbed Micro Edition CLDC implementation and the Jbed RTOS package. The Jbed platform is based upon their FastBCC technology, which dynamically loads and executes Java bytecode at native speeds (much like the goals of the Project Monty KVMs). One key advantage of Esmertec is that the Jbed CLDC implementation can run on a variety of different hardware platforms ­ with or without an operating system! Esmertec implemented their Bluetooth stack completely in Java, and they support GAP, SDAP, SPP, LAP, and PAN on a wide array of Bluetooth hardware modules. They also included support for Palm OS and Pocket PC devices.

Smart Network Devices (www.smartnd.com) has a unique approach in their Java Bluetooth development kit; they include all the components shown in Figure 1, section B, for a complete Java Bluetooth­enabled device: a Bluetooth device (radio), a Bluetooth stack, Bluetooth profiles, a KVM, and the JSR-82 Java Bluetooth APIs. Their product is called Micro BlueTarget Starter Kit ­ Java version (see Figure 2), based on the Micro BlueTarget reference board. It supports the GAP, SDAP, SPP, and GOEP profiles. The Micro BlueTarget is a not a peripheral (like the 3Com Bluetooth module in Figure 3). It's a self-contained Java Bluetooth host device, so it doesn't need to be connected to a host computer to operate. It has its own operating system and KVM built in, and you can download your code to the device using its Ethernet or RS232 interface. You can buy the complete Java Bluetooth development kit for $2,880 and the Micro BlueTarget boards in single quantities for $425.

Figure 2
Figure 2

Figure 3
Figure 3

The Advantages of Java and Bluetooth
Let's look at a scenario where life is made simpler using Java and Bluetooth technology: the Java Shared Whiteboard. Three employees of Acme Widgets Inc. need to have an impromptu meeting. Unfortunately, no conference rooms are available, so the team is forced to hold their meeting in the cafeteria. They would have preferred using a conference room because each room is equipped with an electronic whiteboard. However, since every member of the team has a Java Bluetooth­enabled PDA, their meeting in the cafeteria is very productive.

One member has a new program for his PDA called the Java Shared Whiteboard. Using Bluetooth technology, he sends that program to the rest of the team. Using Over-the-Air Provisioning (OTA) provided by J2ME, each member installs and runs the application on the fly. The meeting can now begin because the whiteboard is shared among the PDAs. Each participant can draw figures on his or her device and the image will appear instantly on the other screens. To save time, one member can take notes and send them to everyone's device while the meeting is in progress.

What are the benefits of Java and Bluetooth? Of course, Java gives you platform independence for the Shared Whiteboard application. Therefore, you don't need to worry about what kind of PDA your fellow team members have (Palm, Pocket PC, Sharp, Sony, Handspring, etc.) as long as a compatible KVM and libraries are available. Bluetooth has an additional benefit ­ it enables you to create instant wireless networks with these devices in order to collaborate and share data. This network is portable, so you can move it to the cafeteria, a conference room, or outside ­ it doesn't matter.

Summary
It's a great time to be a wireless developer. Bluetooth enables you to share and collaborate in ways never imagined. Now, I can enable my clunky old desktops, laptops, and PDAs to participate in a wireless network by simply adding a KVM and a Bluetooth radio. The fun is just beginning.

.  .  .

Book Overview
We've only scratched the surface with Bluetooth. In our upcoming book, Java Bluetooth, Ranjith Antony (my coauthor) and I show how to use Java and Bluetooth with multiple vendor SDKs and Bluetooth devices. We'll also cover many practical scenarios for using Java and Bluetooth in the real world for file transfer, security, and encryption using a simulator, wireless printing, and much more. The advanced chapters will even show you how to use Bluetooth in a Jini network.

Author Bio
Bruce Hopkins is a senior Java consultant at Great Lakes Technologies Group in Southfield, MI. He has worked with Java for over six years, and has researched in wireless networking for four. Bruce is the coauthor of an upcoming book entitled Java Bluetooth by Apress (November 2002). [email protected]

	



Listing 1
...
// lets name our variables
StreamConnectionNotifier notifier = null;
StreamConnection sconn = null;
LocalDevice localdevice = null;
ServiceRecord servicerecord = null;


// step #1
// the String url will already be defined with the
// correct url parameters
notifier = (StreamConnectionNotifier)Connector.open(url);


// step #2
// we will get the LocalDevice if not already done so
localdevice = LocalDevice.getLocalDevice();
servicerecord = localdevice.getRecord(notifier);


// step #3 is optional


// step #4
// this step will block the current thread until a client responds
// this step will also cause the service record to be
// stored in the SDDB
notifier.acceptAndOpen();


// step #5
// just wait...
// assume the client has connected and you are ready to exit


// step #6
// this causes the service record to be removed
// from the SDDB
notifier.close();


Listing 2
...
// let's name our variables


StreamConnectionNotifier notifier = null;
StreamConnection con = null;
LocalDevice localdevice = null;
ServiceRecord servicerecord = null;
InputStream input;
OutputStream output;


// let's create a URL that contains a UUID that
// has a very low chance of conflicting with anything
String url = 
"btspp://localhost:0011223344556677889900AABBCCDDEEFF;name=serialconn";
 
// let's open the connection with the url and cast it into a
StreamConnectionNotifier
notifier = (StreamConnectionNotifier)Connector.open(url);


// block the current thread until a client responds
con = notifier.acceptAndOpen();


// the client has responded, so open some streams
input = con.openInputStream();
output = con.openOutputStream();


// now that the streams are open, send and receive some data

 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.