How to discover bluetooth services using J2ME
Author : Abernala
From TechnologicalWiki
Contents |
[edit] Introduction
This article describes the client API used to discover services that are available on a service discovery server. Class DiscoveryAgent provides the methods to search for services on a Bluetooth server device and to initiate device and service discovery transactions. This API does not support searching for services on the local device.
[edit] API Overview
The process by which a client can discover services is described in the SDAP[1], including all of the SDP[2] capabilities. SDP and the GAP[3] together provide the SDAP functionality. This specification supports the following SDAP functionality:
- searching for services of a particular class;
- retrieving service attributes of a service;
- simultaneously searching for services and retrieving their attributes; and
- terminating a service search transaction in progress.
To discover services available on service discovery servers, the client application first should retrieve an object that encapsulates the SDAP functionality. This object of type DiscoveryAgent is a global singleton object. Pseudocode to retrieve the DiscoveryAgent is given next:
DiscoveryAgent da = LocalDevice.getLocalDevice().getDiscoveryAgent();
[edit] Service Discovery Classes
[edit] class javax.bluetooth.UUID
The class UUID encapsulates unsigned integers that are 16 bits, 32 bits or 128 bits long. The class is used to represent a universally unique identifier used widely as the value for a service attribute. Only service attributes represented by UUIDs are searchable in Bluetooth SDP. The Bluetooth specification defines a few “short” (16-bit or 32-bit) UUIDs and describes how a 16-bit or 32-bit UUID is converted to a 128-bit UUID. This promotion is required for matching; normally only 128-bit UUIDs are compared.
[edit] class javax.bluetooth.DataElement
This class contains the various data types that a Bluetooth service attribute value can take on. Valid service attribute data types include:
- signed and unsigned integers that are one, two, four, eight or sixteen bytes long,
- String,
- boolean,
- UUID, and
- sequences of any one of these scalar types.
The class also presents an interface to construct and retrieve the value of a service attribute. Note that all Bluetooth Service Discovery Protocol related values accessible through the Bluetooth API must be presented to applications in a form that requires no conversion with respect to endianness/byte order. If, in the underlying Bluetooth stack, these values have an endianness/byte order that is different from the one required in Java by the Java Virtual Machine Specification (big endian), then the Bluetooth API implementation must perform all necessary conversions.
[edit] interface javax.bluetooth.ServiceRecord
This interface defines the Bluetooth Service Record, which contains attribute ID, value pairs. A Bluetooth attribute ID is a 16-bit unsigned integer and an attribute value is a DataElement. A DataElement is a self-describing value of one of the types listed in Section 5.3.2. In addition to providing the remote Bluetooth server device from which a ServiceRecord was obtained, this interface has a method populateRecord() to retrieve desired service attributes.
[edit] class javax.bluetooth.DiscoveryAgent
The class DiscoveryAgent provides methods for service and device discovery. It supports service discovery in non-blocking mode and provides a way to cancel a service search transaction in progress.
[edit] interface javax.bluetooth.DiscoveryListener
This interface allows an application to specify an event listener that responds to device and service discovery events. The method servicesDiscovered() is called whenever services are discovered. When a service search transaction is completed or canceled, the serviceSearchCompleted() method is called.
[edit] Example Code
Bluetooth.java
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.bluetooth.*;
import java.util.*;
public class Bluetooth {
private static Display mDisplay;
/*** Bluetooth class instance ***/
public static Bluetooth mBluetooth;
public LocalDevice mLocalDevice;
public DiscoveryAgent da;
/*** Vector with Services found ***/
public static Vector ListFoundServices = new Vector();
/*** To check if services search is completed ***/
public boolean bServicesSearchCompleted = false;
/*** Constructor ***/
public Bluetooth(){
mBluetooth = this;
}
/**
* Shows an alert when an exception has ocurred
* @param e Exception
* @param s Screen
* @param iType Exception type
*/
public void showAlert(Exception e, Screen s, int iType){
Alert alert;
if(iType == 0){
alert = new Alert("Exception","The exception has ocurred: "+e.getClass().getName(), null, AlertType.ERROR);
}else{
alert = new Alert("Error","Device not selected ", null, AlertType.ERROR);
}
alert.setTimeout(Alert.FOREVER);
mDisplay.setCurrent(alert,s);
}
/**
* Search services in remote device
* @param remoteDevice RemoteDevice
* @return Vector List of services found
*/
public Vector searchServices(RemoteDevice remoteDevice){
try{
ListFoundServices.removeAllElements();
// The possibles services are identified by UUID code.
int[] services = {0x0001,0x0003,0x0008,0x000C,0x0100,0x000F,0x1101,0x1000,0x1001,0x1002,0x1115,0x1116,0x1117};
UUID[] uuid = {new UUID(0x0100)};//L2CAP services
da.searchServices(services,uuid,remoteDevice,new Listener());
while(!bServicesSearchCompleted)
{
}
bServicesSearchCompleted = false;
return ListFoundServices;
}catch(BluetoothStateException e){
e.printStackTrace();
//showAlert(e, mDevice,0);
return ListFoundServices;
}
}
/**
* Discovery listener handler
*/
public class Listener implements DiscoveryListener{
/**
* Called when service is found during service search
* @param transID int
* @param servRecord ServiceRecord
*/
public void servicesDiscovered(int transID, ServiceRecord[] servRecord){
System.out.println("A remote service found");
for(int i=0;i<servRecord.length;i++){
ServiceRecord record = servRecord[i];
ListFoundServices.addElement(record);
}
}
/**
* Called when service search is completed
* @param transID int
* @param respCode int
*/
public void serviceSearchCompleted(int transID, int respCode){
System.out.println("Services search completed");
bServicesSearchCompleted = true;
if(respCode==SERVICE_SEARCH_COMPLETED || respCode==SERVICE_SEARCH_NO_RECORDS){
}else{
Alert alert = new Alert("Attention","Search not completed",null, AlertType.INFO);
alert.setTimeout(Alert.FOREVER);
}
}
}
}
[edit] References
- JSR 82: Java APIs for Bluetooth
- JSR 30: J2METM Connected, Limited Device Configuration
- JSR 139: Connected Limited Device Configuration 1.1
- Service Discovery Application Profile (SDAP)
[edit] Notes
- ↑ Service Discovery Application Profile (SDAP) describes how an application should use SDP to discover services on a remote device. SDAP requires that any application be able to find out what services are available on any Bluetooth enabled device it connects to. More info here.
- ↑ Service Discovery Protocol (SDP) enables network devices, applications, and services to seek out and find other complementary network devices, applications, and services needed to properly complete specified tasks. More info here.
- ↑ Generic Access Profile (GAP) provides the basis for all other profiles.


