⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bluetoothdevicediscovery.java

📁 关于J4ME J2ME实例
💻 JAVA
字号:
//#ifndef BLACKBERRY
//
// BlackBerry devices before JDE 4.2.1 did not support JSR-82 and
// will fail to load because of this class.  BlackBerry phones that
// do support JSR-82 are the 8300 (Curve) and 8800 (other 8x00 can
// be upgraded).

package org.j4me.bluetoothgps;

import java.io.IOException;

import java.util.Enumeration;
import java.util.Vector;

import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DataElement;
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.bluetooth.UUID;
import org.j4me.logging.*;

/**
 * Looks for Bluetooth devices (within 10 meters) and returns their
 * names and addresses.
 */
class BluetoothDeviceDiscovery
	implements DiscoveryListener {

    /**
     * Indicates device discovery is in progress
     */
    public static final int INQUIRY_IN_PROGRESS = -1;

    /**
     * Indicates service search is in progress
     */
    public static final int SERVICE_SEARCH_IN_PROGRESS = -1;

    /**
     * Keeps the discovery agent reference.
     */
    private DiscoveryAgent discoveryAgent;

    /**
     * A list of discovered devices.  This is a list of {@link RemoteDevice} objects.
     */
    private Vector discoveredDevices = new Vector();

    /**
     * The list of discovered services for the selected device
     */
    private Vector services = new Vector();

    /**
     * The result of the inquiry.  When the inquiry is done this result will
     * be positive number and have one of the following values.
     * <p>
     * {@link DiscoveryListener#INQUIRY_COMPLETED}
     * {@link DiscoveryListener#INQUIRY_ERROR}
     * {@link DiscoveryListener#INQUIRY_TERMINATED}
     * <p>
     * While it is searching it will have the following value
     * <p>
     * {@link #INQUIRY_IN_PROGRESS}
     */
    private int deviceDiscoveryResult = -1;

    /**
     * The result of the service search.  When the inquiry is done this result
     * will be a positive number and have one of the following values.
     * <p>
     * {@link DiscoveryListener#SERVICE_SEARCH_COMPLETED}
     * {@link DiscoveryListener#SERVICE_SEARCH_TERMINATED}
     * {@link DiscoveryListener#SERVICE_SEARCH_ERROR}
     * {@link DiscoveryListener#SERVICE_SEARCH_NO_RECORDS}
     * {@link DiscoveryListener#SERVICE_SEARCH_DEVICE_NOT_REACHABLE}
     * <p>
     * While is is searching it will have the following value
     * {@link #SERVICE_SEARCH_IN_PROGRESS}
     */
    private int serviceSearchResult = -1;

	/**
	 * Uses Bluetooth device discovery to get a list of the nearby devices
	 * that are turned on and accepting connections (within 10 meters).
	 * <p>
	 * Discovering Bluetooth devices is a lengthy operation.  It usually takes
	 * more than ten seconds.  Therefore this method call normally should
	 * be made from a separate thread to keep the application responsive.
	 * 
	 * @return An array of all the nearby Bluetooth devices that will accept
	 *  a connection, not just GPS devices.  Each array element returns another
	 *  <code>String[2]</code> where the first element is the device's human readable
	 *  name and the second is the address (devices that do not support human
	 *  readable names will be set to the address).  If the operation completed
	 *  successfully, and no devices are nearby, the returned array will have
	 *  length 0.  If the operation terminated, for example because the device
	 *  does not support the Bluetooth API, the returned array will be <code>null</code>.
	 * @throws IOException if any Bluetooth I/O errors occur.  For example if
	 *  another Bluetooth discovery operation is already in progess. 
	 * @throws SecurityException if the user did not grant access to Bluetooth
	 *  on the device.
	 */
    public String[][] discoverNearbyDeviceNamesAndAddresses ()
    	throws IOException, SecurityException
    {
		// Start discovering devices.
		doDiscoverDevices();
		
		while ( getDeviceDiscoveryResult() == BluetoothDeviceDiscovery.INQUIRY_IN_PROGRESS )
		{
			try
			{
				Thread.sleep( 20 );
			}
			catch (InterruptedException e)
			{
				// This thread is being killed, just exit.
				return null;
			}
		}
		
		// Did it fail?
		if ( getDeviceDiscoveryResult() != BluetoothDeviceDiscovery.INQUIRY_COMPLETED )
		{
			throw new IOException("Search for Bluetooth devices failed (code " + getDeviceDiscoveryResult() + ").");
		}
		
		// Create a list of the discovered devices.
		Vector discoveredDevices = getDiscoveredDevices();
		Enumeration devices = discoveredDevices.elements();
		String[][] ret = new String[discoveredDevices.size()][2];
		
		for ( int i = 0; devices.hasMoreElements(); i++ )
		{
			RemoteDevice device = (RemoteDevice)devices.nextElement();
			
			String name = device.getFriendlyName( false );
			String address = device.getBluetoothAddress();
			
			if ( name == null )
			{
				name = address;
			}
			
			String[] val = new String[] { name, address };
			ret[i] = val;
		}
		
		return ret;
    }
    
    /**
     * Start the device discovery
     * @throws BluetoothStateException
     */
    public void doDiscoverDevices() throws BluetoothStateException {
        Log.debug("Starting Bluetooth device discovery");

        // create/get a local device and discovery agent
        LocalDevice localDevice = LocalDevice.getLocalDevice();
        discoveryAgent = localDevice.getDiscoveryAgent();

        // place the device in inquiry mode
        discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
    }

    /**
     * Perform service discovery on a remote device.
     *
     * @param remote the remote device to inquire services for
     * @throws BluetoothStateException
     */
    public void doDiscoverService(RemoteDevice remote)
        throws BluetoothStateException {
        //
        // this large array of integer values will tell JABWT to query
        // for all known attributes
        // see https://www.bluetooth.org/foundry/assignnumb/document/service_discovery
        // section 4.5 for meaning of these IDs
        //
        // note: you don't have to retrieve all attribute everytime. in fact, you
        // can put null for attr and retrieve just the default values. that probably
        // good enough for most cases. we list all attributes for demo purpose
        //
        // note: For Nokia 6230, there is a limit (13) of number of attribute to retrieve
        // and this large array will cause error. If you are using Nokia 6230, you should
        // reduce this array to 13 elements. Just pick any 13 of them and make sure you pick
        // 0x0001 (ServiceClassID) so we can display the profiel name

        /* int[] attr = new int[]{0x0000, 0x0001, 0x0002, 0x0003, 0x0004,
             0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D,
             0x0100, 0x0101, 0x0102, 0x0200, 0x0201,
             0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309,
             0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x0310, 0x0311, 0x0312, 0x0313 };
        */
        int[] attr = new int[] {
                0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
                0x0008, 0x0009, 0x000A, 0x000B, 0x000C
            };

        //
        // search for L2CAP services, most services based on L2CAP
        //
        // note: Rococo simulator required a new instance of Listener for
        // every search. not sure if this is also the case in real devices
        discoveryAgent.searchServices(attr, // attributes to retrieve from remote device
            new UUID[] { new UUID(0x0100) }, // search criteria, 0x0100 = L2CAP
            remote, this); // direct discovery response to Listener object
    }

    /**
     * @see javax.bluetooth.DiscoveryListener#deviceDiscovered(javax.bluetooth.RemoteDevice, javax.bluetooth.DeviceClass)
     */
    public void deviceDiscovered(RemoteDevice remoteDevice,
        DeviceClass deviceClass) {
        Log.debug("Discovered device " + remoteDevice.getBluetoothAddress());
        discoveredDevices.addElement(remoteDevice);
    }

    /**
     * @see javax.bluetooth.DiscoveryListener#servicesDiscovered(int, javax.bluetooth.ServiceRecord[])
     */
    public void servicesDiscovered(int arg0, ServiceRecord[] records) {
        if (Log.isInfoEnabled()) {
            Log.info("Found services " + records.length);
        }

        // note: we do not use transId because we only have one search at a time
        for (int i = 0; i < records.length; i++) {
            ServiceRecord record = records[i];

            services.addElement(record);
        }
    }

    /**
     * @see javax.bluetooth.DiscoveryListener#serviceSearchCompleted(int, int)
     */
    public void serviceSearchCompleted(int transID, int respCode) {
        serviceSearchResult = respCode;
    }

    /**
     * @see javax.bluetooth.DiscoveryListener#inquiryCompleted(int)
     */
    public void inquiryCompleted(int inquiryResult) {
        deviceDiscoveryResult = inquiryResult;
    }

    /**
     * Get the list of discovered devices.  This is a list of {@link RemoteDevice}
     * objects.
     *
     * @return a list of bluetooth devices in range
     */
    public Vector getDiscoveredDevices() {
        return discoveredDevices;
    }

    /**
     * Given the friendly name of the device, find the Remote Device
     *
     * @param friendlyName - The friendly name of the bluetooth device
     * @return the remove device.  If the device is not found this will return
     *  <code>null</code>
     */
    public RemoteDevice getDeviceByFriendlyName(String friendlyName)
        throws IOException {
        Enumeration devices = discoveredDevices.elements();

        RemoteDevice device = null;

        while (devices.hasMoreElements()) {
            device = (RemoteDevice) devices.nextElement();

            if (device.getFriendlyName(false).equals(friendlyName)) {
                break;
            }
        }

        return device;
    }

    /**
     * Get the first discovered service from selected remote device.
     * Your application call this method after your app receives COMPLETED
     * callback event. This will return the first service that match your
     * UUIDs in startInquiry().
     *
     * @return ServiceRecord null if no service discovered
     */
    public ServiceRecord getFirstDiscoveredService() {
        if (services.size() > 0) {
            return (ServiceRecord) services.elementAt(0);
        } else {
            return null;
        }
    }

    /**
     * Get the result of the device discovery.
     *
     * @see javax.bluetooth.DiscoveryListener#INQUIRY_COMPLETED
     * @see javax.bluetooth.DiscoveryListener#INQUIRY_ERROR
     * @see javax.bluetooth.DiscoveryListener#INQUIRY_TERMINATED
     *
     * @return a value greater than or equal to 0 when device discovery is
     *  completed.
     */
    public int getDeviceDiscoveryResult() {
        return deviceDiscoveryResult;
    }

    public String getDeviceDiscoveryResultAsString() {
        switch (deviceDiscoveryResult) {
        case DiscoveryListener.INQUIRY_COMPLETED:
            return "Completed";

        case DiscoveryListener.INQUIRY_ERROR:
            return "Error";

        case DiscoveryListener.INQUIRY_TERMINATED:
            return "Terminated";

        default:
            return "Unknown Code";
        }
    }

    /**
     * Get the result of the service search.
     *
     * @return {@link #SERVICE_SEARCH_IN_PROGRESS} if search is still in progress.
     */
    public int getServiceSearchResult() {
        return serviceSearchResult;
    }

    public String getServiceSearchResultAsString() {
        switch (serviceSearchResult) {
        case DiscoveryListener.SERVICE_SEARCH_COMPLETED:
            return "Completed";

        case DiscoveryListener.SERVICE_SEARCH_TERMINATED:
            return "Terminated";

        case DiscoveryListener.SERVICE_SEARCH_ERROR:
            return "Error";

        case DiscoveryListener.SERVICE_SEARCH_NO_RECORDS:
            return "No Records";

        case DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
            return "Device Not Reachable";

        default:
            return "Unknown Code";
        }
    }

    /**
     * Find channel id of this service record.
     * <p>
     * Channel id is store under ProtocolDescriptorList (0x0004) attribute,
     * then under RFCOMM protocol (0x0003) data element.
     *
     * @param serviceRecord - A service record from the bluetooth device
     * @return the channel id.  If the id could not be determined, <code>null</code>
     *  is returned.
     */
    public static String findChannelId(ServiceRecord serviceRecord) {
        // e1 is ProtocolDescriptorList
        DataElement e1 = serviceRecord.getAttributeValue(0x0004);

        for (Enumeration enum1 = (Enumeration) e1.getValue();
                enum1.hasMoreElements();) {
            // e2 is one ProtocolDescriptor
            DataElement e2 = (DataElement) enum1.nextElement();
            Enumeration enum2 = (Enumeration) e2.getValue();

            // e3 is RFCOMM (0x0003)
            DataElement e3 = (DataElement) enum2.nextElement();

            if (e3.getValue().equals(new UUID(0x0003))) {
                // e4 is channel id
                DataElement e4 = (DataElement) enum2.nextElement();
                int id = (int) e4.getLong();

                return Integer.toString(id);
            }
        }

        return null;
    }
}

//#endif // BlackBerry

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -