?? bluetoothdiscovery.java
字號:
// Copyright 2004 Nokia Corporation.
//
// THIS SOURCE CODE IS PROVIDED 'AS IS', WITH NO WARRANTIES WHATSOEVER,
// EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, FITNESS
// FOR ANY PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE
// OR TRADE PRACTICE, RELATING TO THE SOURCE CODE OR ANY WARRANTY OTHERWISE
// ARISING OUT OF ANY PROPOSAL, SPECIFICATION, OR SAMPLE AND WITH NO
// OBLIGATION OF NOKIA TO PROVIDE THE LICENSEE WITH ANY MAINTENANCE OR
// SUPPORT. FURTHERMORE, NOKIA MAKES NO WARRANTY THAT EXERCISE OF THE
// RIGHTS GRANTED HEREUNDER DOES NOT INFRINGE OR MAY NOT CAUSE INFRINGEMENT
// OF ANY PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OWNED OR CONTROLLED
// BY THIRD PARTIES
//
// Furthermore, information provided in this source code is preliminary,
// and may be changed substantially prior to final release. Nokia Corporation
// retains the right to make changes to this source code at
// any time, without notice. This source code is provided for informational
// purposes only.
//
// Nokia and Nokia Connecting People are registered trademarks of Nokia
// Corporation.
// Java and all Java-based marks are trademarks or registered trademarks of
// Sun Microsystems, Inc.
// Other product and company names mentioned herein may be trademarks or
// trade names of their respective owners.
//
// A non-exclusive, non-transferable, worldwide, limited license is hereby
// granted to the Licensee to download, print, reproduce and modify the
// source code. The licensee has the right to market, sell, distribute and
// make available the source code in original or modified form only when
// incorporated into the programs developed by the Licensee. No other
// license, express or implied, by estoppel or otherwise, to any other
// intellectual property rights is granted herein.
//==============================================================================
// Package Statements
//==============================================================================
// Import Statements
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
import java.util.Vector;
import javax.bluetooth.*;
import java.util.Timer;
import java.util.TimerTask;
//==============================================================================
// CLASS (OR INTERFACE) DECLARATIONS
/** The <code>BluetoothDiscovery</code> provides an easy API to search devices
* and services.<br>
* Main methods to use are searchService and waitOnConnection.<br>
* searchService is used to search the vicinity for other BluetoothDevices and
* connect to them if the offered service matches.<br>
* waitOnConnection is used to offer an service and wait on other devices to
* connect to the local device.<br>
* Before these methods are called you usually should setup the name and the service.
* This is done with setName and setServiceUUID.<br>
* Please note that for discoverability mode and for inquiry the LIAC is used, so
* that you will find only devices which are in limited inquiry access mode. This
* is because this Java code is optimized for MIDlet to MIDlet communication, so that
* the same MIDlet is running on local and on remote device. With using LIAC the
* search process is much faster in environments with many Bluetooth devices around.<br>
*/
public class BluetoothDiscovery
extends Alert
implements CommandListener
{
//==============================================================================
// Final variables (Class constants)
/** The CONCEPT_SDK_BUILD constant determines if MIDlet should run in Concept SDK emulator.
* Unfortunately there are a few flaws in the emulator, so that certain functionality
* cannot be used. If you want to debug in the Concept SDK emulator on PC please set the constant
* to true, for the final target (phone) release you should set this to false.
* Also, if CONCEPT_SDK_BUILD is true, a short Alert is shown (in setServiceUUID, which is one of
* the first methods invoked) to make you aware that this is not the final build. <br>
* <img src="doc-files/crop_concept_sdk_build.jpg"><br>
* The Alert is not shown if CONCEPT_SDK_BUILD is false.
*/
static public final boolean CONCEPT_SDK_BUILD = false; // It's public so that it's description is shown in javadoc
// Attribute ID for service name for base language
static private final int SERVICE_NAME_BASE_LANGUAGE = 0x0100;
// The major device class (in CoD) used for phones:
static private final int MAJOR_DEVICE_CLASS_PHONE = 0x0200;
// Search types
/** Searches each device for the service. If a device with the service is found
* the search is cancelled. A connection is setup to that device/service.
* No device is shown to the user. */
static public final int SEARCH_CONNECT_FIRST_FOUND = 1;
/** Searches each device for the service. All devices with the searched service
* will be connected. No devices are shown to the user. */
static public final int SEARCH_CONNECT_ALL_FOUND = 2;
/** Searches for the service on every found device. A list of devices that
* offer the service is displayed to the user. User can stop the service
* search if at least one device has been found. After stop or after all
* devices are shown to the user the user can select one device. This
* device is connected. */
static public final int SEARCH_ALL_DEVICES_SELECT_ONE = 3;
/** Searches for the service on every found device. A list of devices that
* offer the service is displayed to the user. User can stop the service
* search if at least one device has been found. After stop or after all
* devices are shown to the user the user can select one or several devices. These
* devices are connected.
* Note that this functionality is only available on devices which support
* point-to-multipoint connectivity (bluetooth.connected.devices.max > 1). If the
* device supports only point-to-point connectivity (bluetooth.connected.devices.max = 1) the behaviour is the same as
* if SEARCH_ALL_DEVICES_SELECT_ONE would have been used.
*/
static public final int SEARCH_ALL_DEVICES_SELECT_SEVERAL = 4;
/** Maximum number of connectable, active devices according to Bluetooth specification) */
static private final int BLUETOOTH_MAX_DEVICES = 7;
//==============================================================================
// Class (static) variables
//==============================================================================
// Instance variables
private Display display; // The used display
// Bluetooth/JSR82 variables
private LocalDevice localDevice = null; // Reference to LocalDevice
private int previousDiscoverabilityMode = -1; // Used to restore discoverabilty mode afterwards
// UUID:
// x = random, b = BD address of one of my Bluetooth devices (because BD addresses are also unique)
// xxxx xxxx xxxx 1xxx 8xxx bbbbbbbbbbbb
// Eg. for my device = 006057028C19, ie. "00000000000010008000006057028C19"
private String serviceUUID = null;
// The name of the device/service
private String localName = null;
// Used for Client
private DiscoveryAgent discoveryAgent; // Reference to DiscoveryAgent (used for Inquiry)
private Listener listener; // Discovery Listener (used for inquiry)
private int searchType; // Holds the search type the user wants to use
private int serviceSearchTransId; // trans action id for current service search, if there is no serv search this is -1
private Vector urlStrings; // This holds the url strings of the returned services
private Vector foundServiceRecords; // holds all the found service records
private int maxDevices; // Number of max. connectable devices (retrieved by getproperty)
private DeviceList deviceList; // List with devices that is shown to the user.
private String warning; // Warnign presented to the user in case no device or no service was found
// Used for Server
private StreamConnectionNotifier notifier; // For the server
// Used for both
private BluetoothConnection[] btConnections; // All Bluetooth connections
// Will get value of this, so this can be easily accessed from inner classes
private BluetoothDiscovery root;
// Pointer to the progress bar object (used not only for inquiry)
private InqProgressBar progressBar;
// Used for waiting/notify
private Object block_c; // for Client
private Object block_s; // for Server
private Object block_ss; // for termination of service search
private Object block_notifier; // For Notifier.close
//==============================================================================
// Constructors and miscellaneous (finalize method, initialization block,...)
/** Creates an <code>BluetoothDiscovery</code> object.
* @param disp The display object of the MIDlet. Could have been
* obtained by the MIDlet eg. by calling Display.getDisplay( this ).
*
*/
public BluetoothDiscovery( Display disp )
{
super( "" );
// store 'this'
root = this;
// store display
display = disp;
// Initialize
progressBar = null;
deviceList = null;
// Create object used to synchronize/lock
block_c = new Object();
block_s = new Object();
block_ss = new Object();
block_notifier = new Object();
try
{ // Obtain local device object
localDevice = LocalDevice.getLocalDevice();
// Retrieve number of connectable devices
maxDevices = Integer.parseInt( localDevice.getProperty( "bluetooth.connected.devices.max" ) );
// Because of definition with parked devices
if( maxDevices > BLUETOOTH_MAX_DEVICES )
{ // limit to 7
maxDevices = BLUETOOTH_MAX_DEVICES;
}
}
catch(Exception e)
{ // not much that can be done
localDevice = null;
String message = "Error trying to get local device properties: " +
e.getMessage();
ErrorScreen.showError(message, display.getCurrent());
}
} /* End of the constructor method */
/** Closes the Notifier.
* If Notifier is not null, Notifier.close is called . Afterwards
* Notifier is set to null.
*/
private void closeNotifier()
{
synchronized( block_notifier )
{
if( notifier != null )
{
try
{
if( ! CONCEPT_SDK_BUILD )
{ // Does not work correctly in Concept SDK,
// but should be done in real phone to deregister service
notifier.close();
}
}
catch(Exception e)
{
String message = "Error trying to close notifier" +
e.getMessage();
ErrorScreen.showError(message, display.getCurrent());
}
notifier = null;
}
}
}
/**
* Respond to commands.
* @param c The command.
* @param s The displayable object. */
public void commandAction(Command c, Displayable s)
{
switch( c.getCommandType() )
{
case Command.CANCEL:
// User chose to cancel this class
try
{
// Cancel discovery process
if( listener != null )
{ // cancel client
// Info note to user
Alert a = new Alert( "", "Search cancelled", null, AlertType.INFO );
a.setTimeout( 10000 ); // display max. 10 secs
display.setCurrent( a );
// cancel Inquiry
discoveryAgent.cancelInquiry( listener );
// Cancel service search
// Because this has to wait on termination a new thread is required.
// Otherwise the alert above would not be displayed.
waitOnServSearchTermination w = new waitOnServSearchTermination();
w.start();
}
// Remove listener
listener = null;
// This is used to cancel a server session
closeNotifier();
// Stop progress bar (if existing)
if( progressBar != null )
{
progressBar.stop();
progressBar = null;
}
}
catch(Exception e)
{
String message = "Error trying to cancel: " +
e.getMessage();
ErrorScreen.showError(message, display.getCurrent());
}
break;
}
}
/**
* SaveDiscoverability
* Saves the current discoverability mode.
*/
private void saveDiscoverability()
{
try
{
// Store discoverability mode
previousDiscoverabilityMode =
LocalDevice.getLocalDevice().getDiscoverable();
}
catch(Exception e)
{
// We will just ignore, and not try to save it.
}
}
/**
* RestoreDiscoverability
* Restores the discoverability mode.
*/
private void restoreDiscoverability()
{
try
{ // Restore discoverability mode
if( previousDiscoverabilityMode != -1 )
{
localDevice.setDiscoverable( previousDiscoverabilityMode );
}
}
catch( Exception e )
{
// We will just ignore; there is not much we can do.
}
}
/** Sets the local name that is used by the server/device (not the friendly name).
* This can freely be chosen, it could also be the friendly name of the device.
* @param ln Name to be used.
*/
public void setName( String ln )
{
// Store service name
localName = ln;
}
/** Sets the UUID for the service.
* A UUID is made of:
* x = random, b = BD address of one of my Bluetooth devices (because BD addresses are also unique)
* xxxx xxxx xxxx 1xxx 8xxx bbbbbbbbbbbb
* Eg. for my 3650 the BD address is 006057028C19. So I could invent a
* UUID equal to "00000000000010008000006057028C19".
* @param UUID UUID that shall be used.
*/
public void setServiceUUID( String UUID )
{
// store UUID
serviceUUID = UUID;
// Because this is normally one of the first functions called,
// this notification is placed here
if( CONCEPT_SDK_BUILD )
{ // Display note: Reminder that this is build for Conecpt SDK.
// In build for real phones CONCEPT_SDK_BUILD should be set to false.
Alert a = new Alert( "", "CONCEPT SDK Build", null, AlertType.INFO );
a.setTimeout( 1000 );
display.setCurrent( a );
try
{
Thread.sleep( 1000 );
}
catch(InterruptedException e )
{
// We can just ignore
}
}
}
/** Does an Inquiry followed by a service search.
* The user has (depending on parameter) the possibility to select one or more devices.
* The devices are connected and a list of connections is returned.
* @param st Defines the search type. Depending on the search type the user might have to
* select one or more found devices. Allowed values are: <br>
* {@link #SEARCH_CONNECT_FIRST_FOUND SEARCH_CONNECT_FIRST_FOUND},<br>
* {@link #SEARCH_CONNECT_ALL_FOUND SEARCH_CONNECT_ALL_FOUND},<br>
* {@link #SEARCH_ALL_DEVICES_SELECT_ONE SEARCH_ALL_DEVICES_SELECT_ONE}, and<br>
* {@link #SEARCH_ALL_DEVICES_SELECT_SEVERAL SEARCH_ALL_DEVICES_SELECT_SEVERAL}.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -