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);
}
}
J2ME 蓝牙搜索与连接
最新推荐文章于 2024-08-15 14:47:41 发布