We created a simple Bluetooth application this year (Jan 07, p105) where-in a
Bluetooth client communicated with the Bluetooth server and the server sent a
string message to the client. This time we take you a step further in Bluetooth
programming using Java APIs. We will develop a file transfer utility wherein the
server transfers a 'demo.txt' file to the client over Bluetooth. We mentioned
that the implementation of 'Bluetooth Control Center' is left to the vendor and
varies with toolkits used. Thus, we will be presenting the part which remains
independent of toolkits and devices.
Getting started
To start, you need to install one of the vendor specific toolkits from their
respective websites. An option is the kit provided by Atinav from the URL
http://www.avelink.com/asp/indexB.asp?suite=B. This application will follow
the same pattern as the application in January. A Bluetooth client will contact
the server and if the communication is successful, the server will transfer the
file to the client. Let's first start with the client side. Our client Midlet is
a class named FileTransferC. The code for this is as follows:
|
public class FileTransferC implements
DiscoveryListener {
LocalDevice local = null;
DiscoveryAgent agent = null;
int<> attrSet = null;
RemoteDevice btDev = null;
String serviceURL = null;
ClientSession con = null;
HeaderSet hdr = null;
public FTClient() throws BluetoothStateException{
local = LocalDevice.getLocalDevice();
local.getDiscoveryAgent().startInquiry(DiscoveryAgent.GIAC, this);
}
As we mentioned earlier, the first step is about obtaining a handle to the
local device which is done by invoking the getLocalDevice() method. After this a
reference to a DiscoveryAgent object is obtained and presence of other Bluetooth
devices is enquired. In the implementation of deviceDiscovered() method we
simply assign the object to 'btDev' object:
public void deviceDiscovered(RemoteDevice
btDevice,DeviceClass cod){
btDev = btDevice;
System.out.println("Device discovered " +
btDevice.getBluetoothAddress());
}
Next we implement servicesDiscovered() method as follows:
public void servicesDiscovered(int transID,
ServiceRecord<> servRecord){
System.out.println("Discovered a service ....");
for(int i =0; i < servRecord.length; i++){
serviceURL =
servRecord.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT,
true);
System.out.println("The service URL is " + serviceURL);
}
}
Once the services offered are discovered, the client connects to the server
for each of the services. With all this done, we need to get down to some
serious business. For the implementation of searchServiceCompleted(), we code
down the file transfer like this:
public void serviceSearchCompleted(int
transID, int respCode){
try{
con = (ClientSession)Connector.open(serviceURL);
hdr = con.connect(hdr);
System.out.println("Response code of the server after connect..." +
hdr.getResponseCode());
hdr = con.createHeaderSet();
The following code is for sending a request to the server for the demo.txt
file. The server then sends the file over the Bluetooth connection which is
written on the local device using the OutputStream class, after which it is
normal I/O operations.
hdr.setHeader(HeaderSet.TYPE,"text/vCard");
hdr.setHeader(HeaderSet.NAME,"demo.txt");
Operation op = con.get(hdr);
InputStream in = op.openInputStream();
StreamConnection filestream =
(StreamConnection)Connector.open("file://name=demo.txt;mode=w");
OutputStream out = filestream.openOutputStream();
...
You can then implement the
enquiryCompleted() method. Now we come down to the server. Well over here you
first need to initialize the Bluetooth Control Center which differs depending on
the toolkit used, so we straight away get down to the common part:
Public class FileTransferS extends
ServerRequestHandler{
...
public int onConnect(HeaderSet request, HeaderSet reply) {
return ResponseCodes.OBEX_HTTP_OK;
}
The onConnect() method handles the logic for successful connection by sending
a 'Connection OK' message. Next we implement the onGet() method to transfer the
file to the client when the server receives the 'Get' request. Not
any rocket science here as well, as it simply receives the request headers and
opens a connection for the client. After this it writes the file over an
OutputStream.
public int onGet(Operation op) {
try{
HeaderSet hdr = op.getReceivedHeaders();
InputConnection inpcon = (InputConnection)Connector.open("file://name="+(hdr.getHeader(HeaderSet.NAME)).toString()+";mode=r");
InputStream in = inpcon.openInputStream();
byte<> fileAsBytes = new byte<97>;
in.read(fileAsBytes);
DataOutputStream out = op.openDataOutputStream();
out.write(fileAsBytes, 0, fileAsBytes.length);
...
This was how we implemented a basic file transfer utility. Although we could
have used authentication and other additional features as well, we didn't do so
for simplicity.
In real life, it is always good to keep in mind the security policy before
allowing the connection. So, the next time you need to develop a Bluetooth
utility for mobiles, you know which way to head for and how to go about it.