org.openuat.util
Class BluetoothPeerManager

java.lang.Object
  extended by org.openuat.util.BluetoothPeerManager

public class BluetoothPeerManager
extends java.lang.Object

This class implements a Bluetooth peer device manager that handles automatic background discovery. Users of this class should implement the BluetoothPeerManager.DiscoveryEventsHandler interface and register itself with addListener/removeListener to react to events. Parameters for automatic background discovery can be set with setSleepBetweenInquiriesTime, setAutomaticServiceDiscovery, and setAutomaticServiceDiscoveryUUID. The whole inquiry process is started by calling startInquiry, which can either be a one-shot operation or be started as a continuous background thread (which can be stopped with stopInquiry). Services of discovered devices can be found by either calling startServiceSearch directly or setting automaticServiceDiscovery to true. There are two ways of querying the discovered information: either explicitly via getPeers and getServices, or by using the arguments passed to events.


Nested Class Summary
static interface BluetoothPeerManager.PeerEventsListener
          Users of BluetoothPeerManager should most probably implement this interface and register themselves with addListener.
 
Field Summary
static int DEFAULT_SLEEP_TIME
          The default sleep time between two inquiry runs in milliseconds.
static int MAXIMUM_SLEEP_TIME
          The maximum sleep time between two inquiry runs in milliseconds.
static int MINIMUM_SLEEP_TIME
          The minimum sleep time between two inquiry runs in milliseconds.
static int SCAN_SERVICES_FACTOR
          Re-scan services every nth time that a device is discovered by the inquiry process.
static int TIMEOUT_SERVICE_SEARCH
          The maximum time we wait for a service search to finish in milliseconds.
 
Constructor Summary
BluetoothPeerManager()
           
 
Method Summary
 boolean addListener(BluetoothPeerManager.PeerEventsListener listener)
          Add a new event listener.
 boolean getAdaptiveSleepTime()
          Returns the value of adaptiveSleepTime.
 boolean getAutomaticServiceDiscovery()
          Returns the state of automatic service discovery.
 javax.bluetooth.UUID getAutomaticServiceDiscoveryUUID()
          Returns the UUID used for automatically discovering only specific service UUID.
 int getCurrentSleepBetweenInquiriesTime()
          Returns the time to sleep in between two inquiries when startInquiry is called with continuousBackground=true.
 javax.bluetooth.RemoteDevice[] getPeers()
          Returns the list of devices that have been discovered until now.
static java.lang.String getRemoteServiceURL(java.lang.String remoteAddress, javax.bluetooth.UUID serviceUuid, int authenticateEncryptMode, int timeoutMs)
          This is a helper function to return a remote service given a UUID and Bluetooth MAC address.
 javax.bluetooth.ServiceRecord[] getServices(javax.bluetooth.RemoteDevice device)
          Returns the list of services that have been discovered for a device.
 boolean isInquiryActive()
          Returns true if the inquiry thread is currently running.
static void main(java.lang.String[] args)
           
 boolean removeListener(BluetoothPeerManager.PeerEventsListener listener)
          Remove a registered event listener.
static java.lang.String resolveName(javax.bluetooth.RemoteDevice device)
          This is a helper function for resolving a remote device name.
 void setAdaptiveSleepTime(boolean value)
          Sets the value of adaptiveSleepTime.
 void setAutomaticServiceDiscovery(boolean automaticServiceDiscovery)
          Sets the state of automatic service discovery.
 void setAutomaticServiceDiscoveryUUID(javax.bluetooth.UUID uuid)
          Sets the UUID used for automatically discovering only specific service UUID.
 void setSleepBetweenInquiriesTime(int milliseconds)
          Sets the time to sleep in between two inquiries when startInquiry is called with continuousBackground=true.
 boolean startInquiry(boolean continuousBackground)
          Starts a Bluetooth inquiry.
 boolean startServiceSearch(javax.bluetooth.RemoteDevice device, javax.bluetooth.UUID specificService)
          Start to search for the list of services on a remote device.
 boolean stopInquiry(boolean force)
          Stops a background inquiry.
 boolean waitForBackgroundSearchToFinish(int timeoutMs)
          Wait for any background inquiry or service search that may be running to finish.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

DEFAULT_SLEEP_TIME

public static final int DEFAULT_SLEEP_TIME
The default sleep time between two inquiry runs in milliseconds.

See Also:
Constant Field Values

MAXIMUM_SLEEP_TIME

public static final int MAXIMUM_SLEEP_TIME
The maximum sleep time between two inquiry runs in milliseconds. Automatic sleep time adaptation will not set it higher than this.

See Also:
Constant Field Values

MINIMUM_SLEEP_TIME

public static final int MINIMUM_SLEEP_TIME
The minimum sleep time between two inquiry runs in milliseconds. Automatic sleep time adaptation will not set it lower than this.

See Also:
Constant Field Values

TIMEOUT_SERVICE_SEARCH

public static final int TIMEOUT_SERVICE_SEARCH
The maximum time we wait for a service search to finish in milliseconds. After this time, the service search request is canceled.

See Also:
Constant Field Values

SCAN_SERVICES_FACTOR

public static final int SCAN_SERVICES_FACTOR
Re-scan services every nth time that a device is discovered by the inquiry process.

See Also:
Constant Field Values
Constructor Detail

BluetoothPeerManager

public BluetoothPeerManager()
                     throws java.io.IOException
Throws:
java.io.IOException
Method Detail

getCurrentSleepBetweenInquiriesTime

public int getCurrentSleepBetweenInquiriesTime()
Returns the time to sleep in between two inquiries when startInquiry is called with continuousBackground=true.

Returns:
The sleep time in ms.
See Also:
sleepBetweenInquiries

setSleepBetweenInquiriesTime

public void setSleepBetweenInquiriesTime(int milliseconds)
Sets the time to sleep in between two inquiries when startInquiry is called with continuousBackground=true. Note that the actual sleep time will be up to 20% randomly off this time to prevent continuous collisions between two devices doing the same. This may be changed even while a backgound inquiry is running. When setAdaptiveSleepTime(true) is set, then this value will be changed automatically depending on the "volatility" of the Bluetooth inquiry results.

Parameters:
milliseconds - The sleep time in ms.
See Also:
sleepBetweenInquiries, getAdaptiveSleepTime(), setAdaptiveSleepTime(boolean)

getAdaptiveSleepTime

public boolean getAdaptiveSleepTime()
Returns the value of adaptiveSleepTime.


setAdaptiveSleepTime

public void setAdaptiveSleepTime(boolean value)
Sets the value of adaptiveSleepTime.

Parameters:
value - true if the sleep time between two subsequent inquiry runs should be adapted automatically depending on the "volatility" of the Bluetooth inquiry results.

getAutomaticServiceDiscovery

public boolean getAutomaticServiceDiscovery()
Returns the state of automatic service discovery.

Returns:
true if services are discovered automatically for newly found devices.
See Also:
automaticServiceDiscovery

setAutomaticServiceDiscovery

public void setAutomaticServiceDiscovery(boolean automaticServiceDiscovery)
Sets the state of automatic service discovery. This may be changed even while a background inquiry is running.

Parameters:
automaticServiceDiscovery - Set to true if services should be discovered automatically for newly found devices.
See Also:
automaticServiceDiscovery

getAutomaticServiceDiscoveryUUID

public javax.bluetooth.UUID getAutomaticServiceDiscoveryUUID()
Returns the UUID used for automatically discovering only specific service UUID.

Returns:
The service UUID used for automatic service discovery.
See Also:
automaticServiceDiscoveryUUID

setAutomaticServiceDiscoveryUUID

public void setAutomaticServiceDiscoveryUUID(javax.bluetooth.UUID uuid)
Sets the UUID used for automatically discovering only specific service UUID. This may be changed even while a backgound inquiry is running.

Parameters:
uuid - The service UUID used for automatic service discovery. Set to null to not restrict the discovery but search for all available services.
See Also:
automaticServiceDiscoveryUUID

startInquiry

public boolean startInquiry(boolean continuousBackground)
Starts a Bluetooth inquiry.

Parameters:
continuousBackground - If set to true, this start a continuous inquiry in the background, with the time set by setSleepBetweenInquiriesTime between two inquiries. If set to false, it just starts a one-shot inquiry.
Returns:
true if the inquiry could be started, false otherwise (either when another inquiry is already active or due to a Bluetooth error).

stopInquiry

public boolean stopInquiry(boolean force)
Stops a background inquiry.

Parameters:
force - If set to true, then any inquiry or service search that may be running in the background will be canceled. If set to false, they will be left running (and waitForBackgroundSearchToFinish can be used to wait for them to finish).
Returns:
true it stopped successfully, false if no background inquiry was running.

isInquiryActive

public boolean isInquiryActive()
Returns true if the inquiry thread is currently running.


waitForBackgroundSearchToFinish

public boolean waitForBackgroundSearchToFinish(int timeoutMs)
                                        throws java.lang.InterruptedException
Wait for any background inquiry or service search that may be running to finish. It is advisable to call stopInquiry() before this method...

Parameters:
timeoutMs - The maximum amount of time to wait in milliseconds.
Returns:
true if, within timeoutMs milliseconds, no background task is running any more, false otherwise (i.e. if something is still running).
Throws:
java.lang.InterruptedException

startServiceSearch

public boolean startServiceSearch(javax.bluetooth.RemoteDevice device,
                                  javax.bluetooth.UUID specificService)
Start to search for the list of services on a remote device. This should not be done when automaticServiceDiscovery=true for performance reasons (but does not hurt if it is called). Calling this method empties the services list for the given device before the new search to get rid of potentially stale (changed) service entries.

Parameters:
device - The remote device to get the service list from.
specificService - The UUID of a specific service to search for. If set to null, arbitrary services are returned. The UUID 0x0100 (for L2CAP support) is always included in the search, because we only support L2CAP connections anyway (no SCO).
Returns:
true if the service search could be started, false otherwise (most probably due to Bluetooth state issue like an already running inquiry or too many concurrent service searches).

getPeers

public javax.bluetooth.RemoteDevice[] getPeers()
Returns the list of devices that have been discovered until now.

Returns:
The list of devices. If no devices have been discovered yet, the returned array will be valid, but empty.

getServices

public javax.bluetooth.ServiceRecord[] getServices(javax.bluetooth.RemoteDevice device)
Returns the list of services that have been discovered for a device.

Parameters:
device - The device for which the services should be returned. This device must have been discovered before, i.e. it must be in the list of devices returned by getPeers.
Returns:
The list of services found for the given device. When the device is valid but not services have been found, the returned array will be valid but empty. When the device has not been discovered yet or service discovery for it is still in progress, null is returned.

addListener

public boolean addListener(BluetoothPeerManager.PeerEventsListener listener)
Add a new event listener.

Returns:
true if the listener was added, false if it was already found in the list.

removeListener

public boolean removeListener(BluetoothPeerManager.PeerEventsListener listener)
Remove a registered event listener.

Returns:
true if the listener was removed, false if it was not found in the list.

resolveName

public static java.lang.String resolveName(javax.bluetooth.RemoteDevice device)
This is a helper function for resolving a remote device name. If the name can not be queried or is empty, then the Bluetooth (MAC) address will be returned instead. This method takes care of the Bluetooth exception that can occur when trying to resolve the name and will always return a valid string object.

Parameters:
device - The remote device to resolve the name for.

getRemoteServiceURL

public static java.lang.String getRemoteServiceURL(java.lang.String remoteAddress,
                                                   javax.bluetooth.UUID serviceUuid,
                                                   int authenticateEncryptMode,
                                                   int timeoutMs)
                                            throws java.io.IOException
This is a helper function to return a remote service given a UUID and Bluetooth MAC address. It blocks during inquiry and service search and can thus take easily up to 30 seconds to return!

Parameters:
remoteAddress - The Bluetooth MAC address of the remote device.
serviceUuid - The UUID of the service to search for.
authenticateEncryptMode - See ServiceRecord, use e.g. ServiceRecord.NOAUTHENTICATE_NOENCRYPT
timeoutMs - The maximum amount of time to wait in milliseconds.
Returns:
The complete URL to the service if it was found (that is, a service with the specified UUID at the specified device) or null otherwise.
Throws:
java.io.IOException

main

public static void main(java.lang.String[] args)
                 throws java.io.IOException
Throws:
java.io.IOException


2005-2009, Rene Mayrhofer.