Subscribe to News

How to discover bluetooth services using J2ME

Author : Abernala

From TechnologicalWiki

Jump to: navigation, search

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

[edit] Notes

  1. 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.
  2. 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.
  3. Generic Access Profile (GAP) provides the basis for all other profiles.
Main Collaborators