Device discovery is the first step required when browsing nearby Bluetooth devices. When we have discovered nearby devices we can find out which services they offer. Note that no UI specific code is included in these examples, only Bluetooth specific code.
To use any Bluetooth related methods you need to obtain a reference to the LocalDevice object. This is
done with a call to LocalDevice.getLocalDevice(). LocalDevice gives you access to Bluetooth
properties for the device, such as Bluetooth address, friendly name and discovery mode. We will use LocalDevice
to obtain a DiscoveryAgent. The DiscoveryAgent object gives you access to device discovery and service search.
The MIDlet now looks like this:
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.MIDlet;
public class yourMIDlet extends MIDlet implements CommandListener,
DiscoveryListener {
private LocalDevice local = null;
private DiscoveryAgent agent = null;
private Vector devicesFound = null;
public void startApp() {
/* Add your MIDlet specific code here.
* You probably want to show the user
* a welcome screen.
* The call to doDeviceDiscovery() is
* here for the example's sake. You
* should call doDeviceDiscovery() when
* the user actively asks for it.
*/
doDeviceDiscovery();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
}
public void deviceDiscovered(RemoteDevice remoteDevice,
DeviceClass deviceClass) {
}
public void inquiryCompleted(int param) {
}
public void serviceSearchCompleted(int param, int param1) {
}
public void servicesDiscovered(int param,
ServiceRecord[] serviceRecord) {
}
private void doDeviceDiscovery() {
try {
local = LocalDevice.getLocalDevice();
}catch (BluetoothStateException bse) {
// Error handling code here
}
agent = local.getDiscoveryAgent();
devicesFound = new Vector();
try {
if(!agent.startInquiry(DiscoveryAgent.GIAC,this)) {
//Inquiry not started, error handling code here
}
}catch(BluetoothStateException bse) {
//Error handling code here
}
}
}
Device discovery is started using the LocalDevice and DiscoveryAgent objects.
Searching with the General Inquiry Access Code (GIAC) parameter will find devices which are general discoverable. The DiscoveryListener parameter
is this, meaning our MIDlet. When devices are discovered or the search is complete, events will be delivered to our MIDlet.
Then the deviceDiscovered() and inquiryCompleted() methods come into play. When a device is discovered the deviceDiscovered()
method of the object this will be called. The parameter remoteDevice will be the discovered device, it is up to us to decide what to do with it.
We do not know how many devices will be discovered. A Vector will therefore be an appropriate data structure to save discovered devices.
The inquiryCompleted() method is called when the inquiry ends. You should check the status code supplied in the parameter param.
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.MIDlet;
public class yourMIDlet extends MIDlet implements CommandListener,
DiscoveryListener {
private LocalDevice local = null;
private DiscoveryAgent agent = null;
Vector devicesFound = null;
public void startApp() {
/* Add your MIDlet specific code here.
* You probably want to show the user
* a welcome screen.
* The call to doDeviceDiscovery() is
* here for the example's sake. You
* should call doDeviceDiscovery when
* the user actively asks for it.
*/
doDeviceDiscovery();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable d) {
}
public void deviceDiscovered(RemoteDevice remoteDevice,
DeviceClass deviceClass) {
devicesFound.addElement(remoteDevice);
}
public void inquiryCompleted(int param) {
/* We should give the user an alert based on the
* inquiry status code
*/
switch (param) {
case DiscoveryListener.INQUIRY_COMPLETED:
// Inquiry completed normally, add appropriate code here.
break;
case DiscoveryListener.INQUIRY_ERROR:
// Error during inquiry, add appropriate code here.
break;
case DiscoveryListener.INQUIRY_TERMINATED:
/* Inquiry terminated, caused by agent.cancelInquiry()
* Add appropriate code here.
*/
break;
}
}
public void serviceSearchCompleted(int param, int param1) {
}
public void servicesDiscovered(int param,
ServiceRecord[] serviceRecord) {
}
private void doDeviceDiscovery() {
try {
local = LocalDevice.getLocalDevice();
}catch (BluetoothStateException bse) {
// Error handling code here
}
agent = local.getDiscoveryAgent();
devicesFound = new Vector();
try {
if(!agent.startInquiry(DiscoveryAgent.GIAC,this)) {
//Inquiry not started, error handling code here
}
}catch(BluetoothStateException bse) {
//Error handling code here
}
}
}
We now keep discovered devices in the foundDevices Vector by adding them as they are discovered. When our search ends, we check if
everything went as expected and can alert the user by adding appropriate code in our switch-statement.
This page was last updated 14. Jul. 2006
Comments and feedback are highly appreciated.
You can reach me at: klings (at) nowires (dot) org