J2ME 蓝牙搜索与连接
import java.io.IOException;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 javax.microedition.io.Connection;import javax.microedition.io.Connector;/** * 蓝牙设备搜索及服务搜索类<BR> * * * @author Administrator * @version V1.0 */public final class BlueTooth implements DiscoveryListener , Runnable{ /** * 准备 */ public static final int STATUS_READY = 0x01; /** * 设备搜索中 */ public static final int STATUS_DEV_SEARCHING = 0x02; /** * 设备搜索完成 */ public static final int STATUS_DEV_SEARCH_FINISH = 0x03; /** * 设备搜索失败 */ public static final int STATUS_DEV_SEARCH_ERROR = 0x04; /** * 服务搜索中 */ public static final int STATUS_SER_SEARCHING = 0x10; /** * 服务搜索完成 */ public static final int STATUS_SER_SEARCH_FINISH = 0x11; /** * 服务搜索失败 */ public static final int STATUS_SER_SEARCH_ERROR = 0x12; /** * 创建与服务的连接中 */ public static final int STATUS_CONNECTING = 0x20; /** * 创建服务连接成功 */ public static final int STATUS_CONNECT_OK = 0x21; /** * 创建服务连接失败 */ public static final int STATUS_CONNECT_FAIL = 0x22; /** * 单实例 */ private static BlueTooth instance = new BlueTooth(); /** * 本地设备 */ protected LocalDevice localDevice; /** * 设备搜索代理 */ protected DiscoveryAgent discoveryAgent; /** * 搜索到的设备列表 */ protected Vector remoteDeviceVector = new Vector(); /** * 搜索到的服务信息列表 */ protected Vector serviceInfoVector = new Vector(); /** * 搜索到的服务列表 */ protected Vector serviceRecordVector = new Vector(); /** * */ // protected int connectType = 0; /** * 状态 */ protected int status = 0; /** * 是否支持蓝牙 */ protected boolean supportJSR82 = false; /** * 对象锁,控制设备搜索和服务搜索 */ private Object bluelock = new Object(); /** * 过滤器 */ private Filter filter; /** * 预设设备 */ private String expectDevice; /** * 构造子 */ private BlueTooth() { try { Class.forName("javax.bluetooth.LocalDevice"); supportJSR82 = true; } catch (Exception ex) { supportJSR82 = false; } try { // 获得本地设备 localDevice = LocalDevice.getLocalDevice(); // 获得本地设备代理 discoveryAgent = localDevice.getDiscoveryAgent(); } catch (Exception e) { supportJSR82 = false; } } /** * 获取单实例 * * @return 静态单实例 */ public static BlueTooth getInstance() { return instance; } /** * 搜索蓝牙设备 * * @return 搜索到的蓝牙设备 */ public Vector findDevices() { remoteDeviceVector.removeAllElements(); try { // 启动搜索代理发现设备并与DiscoveryListener注册回调 discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this); // 设备搜索状态 setStatus(STATUS_DEV_SEARCHING); // 设备搜索过程是异步的,这里需要同步搜索过程 // 设备搜索完毕会通知主线程继续运行 synchronized (bluelock) { // 加上while,break纯粹是为了规避findbugs检查 while (status >= STATUS_READY && status < STATUS_DEV_SEARCH_FINISH) { try { bluelock.wait(); // break; } catch (Exception e) { break; } } } } catch (BluetoothStateException e) { setStatus(STATUS_DEV_SEARCH_ERROR); } return remoteDeviceVector; } /** * 获取手机匹配装置列表中的蓝牙设备集合 * * @return 搜索到的蓝牙设备 */ public Vector findDeviceInCache() { Vector vector = new Vector(); RemoteDevice[] rds = discoveryAgent.retrieveDevices(DiscoveryAgent.CACHED); if (rds != null) { for (int i = 0; i < rds.length; i++) { vector.addElement(rds[i]); } } rds = discoveryAgent.retrieveDevices(DiscoveryAgent.PREKNOWN); if (rds != null) { for (int i = 0; i < rds.length; i++) { vector.addElement(rds[i]); } } return vector; } /** * 取消正在执行的设备搜索 */ public void cancelFindDevices() { if (status == STATUS_DEV_SEARCHING) { discoveryAgent.cancelInquiry(this); } } /** * 蓝牙设备发现时的回调方法<BR> * 每发现一个蓝牙装置,此方法将被调用一次。 * * @param btDevice 搜索到的蓝牙装置 * @param cod 服务类,远程蓝牙装置的主设备类或附设备类 * @see javax.bluetooth.DiscoveryListener#deviceDiscovered(javax.bluetooth.RemoteDevice, * javax.bluetooth.DeviceClass) */ public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) { if (filter != null && !filter.match(btDevice)) { return; } else { remoteDeviceVector.addElement(btDevice); } if (expectDevice != null && expectDevice.equals(btDevice.getBluetoothAddress())) { discoveryAgent.cancelInquiry(this); } } /** * 设备搜索结束时的回调方法<BR> * * * @param discType 搜索请求结束类型; 为INQUIRY_COMPLETED, INQUIRY_TERMINATED, 或INQUIRY_ERROR * @see javax.bluetooth.DiscoveryListener#inquiryCompleted(int) */ public void inquiryCompleted(int discType) { if (discType == INQUIRY_COMPLETED) { setStatus(STATUS_DEV_SEARCH_FINISH); } else if (discType == INQUIRY_ERROR) { setStatus(STATUS_DEV_SEARCH_ERROR); } // 蓝牙搜索执行完毕,通知主线程继续 synchronized (bluelock) { bluelock.notifyAll(); } } /** * 搜索蓝牙设备提供的服务 * * @param device 远程蓝牙设备 * @param uuids 搜索服务UUID数组 * @return 搜索到的服务集合 */ public Vector findServices(RemoteDevice device, UUID[] uuids) { serviceInfoVector.removeAllElements(); serviceRecordVector.removeAllElements(); try { discoveryAgent.searchServices(new int[] {0x100 }, uuids, device, this); setStatus(STATUS_SER_SEARCHING); } catch (BluetoothStateException e) { setStatus(STATUS_SER_SEARCH_ERROR); } synchronized (bluelock) { // 加上while,break纯粹是为了规避findbugs检查 while (status > STATUS_DEV_SEARCHING && status <= STATUS_SER_SEARCHING) { try { bluelock.wait(); // break; } catch (InterruptedException e) { break; } } } return serviceRecordVector; } /** * 搜索服务时找到服务的回调方法<BR> * [功能详细描述] * * @param transID 服务搜索事务ID * @param servRecord 搜索到的服务记录数组 * @see javax.bluetooth.DiscoveryListener#servicesDiscovered(int, javax.bluetooth.ServiceRecord[]) */ public void servicesDiscovered(int transID, ServiceRecord[] servRecord) { if (servRecord != null) { for (int i = 0; i < servRecord.length; i++) { DataElement serviceNameElement = servRecord[i].getAttributeValue(0x0100); String serviceName = (serviceNameElement.getValue().toString()).trim(); ServiceInfo info = new ServiceInfo(); info.name = serviceName; serviceInfoVector.addElement(info); serviceRecordVector.addElement(servRecord[i]); } } } /** * 搜索服务结束回调方法<BR> * 结束包含正常结束,手动终止或错误 * * @param transID 搜索事务ID * @param respCode 搜索响应码 * @see javax.bluetooth.DiscoveryListener#serviceSearchCompleted(int, int) */ public void serviceSearchCompleted(int transID, int respCode) { switch (respCode) { case DiscoveryListener.SERVICE_SEARCH_COMPLETED: case DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE: case DiscoveryListener.SERVICE_SEARCH_NO_RECORDS: case DiscoveryListener.SERVICE_SEARCH_TERMINATED: { setStatus(STATUS_SER_SEARCH_FINISH); break; } case DiscoveryListener.SERVICE_SEARCH_ERROR: { setStatus(STATUS_SER_SEARCH_ERROR); break; } default: { setStatus(STATUS_SER_SEARCH_FINISH); break; } } synchronized (bluelock) { bluelock.notifyAll(); } } /** * 线程run方法<BR> * 搜索设备 * * @see java.lang.Runnable#run() */ public void run() { if (supportJSR82) { findDevices(); } } /** * 根据服务URL创建连接 * * @param url 从ServiceRecord中获取的服务URL * @return 创建的连接 * @exception IOException 当创建连接失败时,抛出IO异常 */ public Connection getConnection(String url) throws IOException { Connection conn = null; try { setStatus(STATUS_CONNECTING); conn = Connector.open(url); setStatus(STATUS_CONNECT_OK); // RemoteDevice rd = RemoteDevice.getRemoteDevice(conn); } catch (IOException e) { setStatus(STATUS_CONNECT_FAIL); throw e; } return conn; } /** * 根据服务记录创建连接 * * @param service 搜索记录 * @return 创建的连接 * @exception IOException 当创建连接失败时,抛出IO异常 */ public Connection getConnection(ServiceRecord service) throws IOException { String url = service.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); return getConnection(url); } // -----------------> getter & setter /** * 获取搜索到的蓝牙设备列表<br /> * 如果要获取最终的设备列表,需要在status=STATUS_DEV_SEARCH_FINISH时,再调用此方法 * * @return 搜索到的蓝牙设备列表 */ public Vector getRemoteDeviceVector() { return remoteDeviceVector; } /** * 获取搜索到的服务列表 * * @return 搜索到的ServiceRecord列表 */ public Vector getServiceRecordVector() { return serviceRecordVector; } /** * 获取搜索到的服务信息列表 * * @return 搜索到的ServiceRecord信息列表 */ public Vector getServiceInfoVector() { return serviceInfoVector; } /** * 获取当前状态 * * @return 状态 */ public int getStatus() { return status; } /** * 设置状态 * * @param status 要设置的状态 */ public void setStatus(int status) { this.status = status; } /** * 判断是否支持jsr82规范 * * @return 是否支持蓝牙 */ public boolean isSupportJSR82() { return supportJSR82; } /** * 设置搜索过滤器 * * @param filter 搜索设备时的过滤器 */ public void setFilter(Filter filter) { this.filter = filter; } /** * 获取设备过滤器 * * @return 设备过滤器 */ public Filter getFilter() { return filter; } /** * 设备搜索过滤器<BR> * 如果符合匹配条件,则将搜索到的设备加入搜索结果集合当中 * * @author Adminstrator * @version V1.0 */ public static abstract class Filter { /** * 判断设备是否符合过滤规则 * * @param device 搜索到的设备 * @return 是否符合过滤规则 */ public abstract boolean match(RemoteDevice device); }}