蓝牙操作线程类
一、变量声明
/**
*
* @name 蓝牙操作线程
* @descripation 完成蓝牙相关操作:开启、搜索发现、查询配对设备信息、建立与目标设备的连接、进行数据传输、释放连接等
* @date 2014-3-22
* @version 1.0
*/
public class BluetoothDeviceAdapter implements Runnable {
protected Context context;
protected UUID MY_UUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
protected Map<String, String> measureResult;
protected BluetoothDevice bluetoothDevice;
protected BluetoothAdapter bluetoothAdapter;
protected static BluetoothReciever bluetoothReceiver;
protected BluetoothSocket socket;
protected Handler handlerBluetooth;
protected InputStream inputStream;
protected OutputStream outputStream;
public int dataLeng = 32;
private byte dataHead = (byte) 0x0A;
private String DEVICE_NAME = "XIESHIJIE";
解析:
UUID是作为蓝牙串口唯一标识,用于蓝牙通讯,
BluetoothDevice是作为远程蓝牙连接设备,BluetoothAdapter作为本地蓝牙调用的接口
BluetoothSocke用于蓝牙通信,类似于socket和serversocket
DEVICE_NAME是用来定义想要连接的设备的名称,根据不同设备来自定义此变量
二、构造方法
/**
* 构造方法:获取本地蓝牙实例,打开蓝牙,搜索设备信息,查询已配对的设备
*
* @param handler
* @throws IOException
*/
public BluetoothDeviceAdapter(Context context, Handler handler) {
Log.w("BluetoothDeviceAdapter()", "获取本地蓝牙实例,打开蓝牙,搜索设备信息,查询已配对的设备");
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
openBluetoothAdapter();
// registerAndDiscover();
queryPairedDevicesInfo();
this.context = context;
this.handlerBluetooth = handler;
measureResult = new HashMap<String, String>();
}
/**
* 根据当前本地蓝牙适配器的状态选择性询问用户启动它
*/
protected void openBluetoothAdapter() {
Log.w("openBluetoothAdapter()", "打开本地蓝牙" + bluetoothAdapter.getName());
if (bluetoothAdapter != null) {
if (!bluetoothAdapter.isEnabled()) {
bluetoothAdapter.enable();
Log.i("openBluetoothAdapter", "当前状态为关闭,系统自动打开");
}
} else {
Log.i("openBluetoothAdapter()", "本地设备驱动异常!");
}
}
/**
* 查询已配对的设备
*/
private void queryPairedDevicesInfo() {
// 通过getBondedDevices方法来获取已经与本设备配对的远程设备信息列表
Log.w("queryPairedDevicesInfo()", "查询已配对的设备");
Set<BluetoothDevice> pairedDevices = bluetoothAdapter
.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
Log.i("已配对的设备名称", device.getName());
Log.i("已配对的设备地址", device.getAddress());
// 查找已配对的,按此目标创建远程bluetoothDevice
if (DEVICE_NAME.equals(device.getName())) {
Log.w("发现目标设备,按此创建远程端", DEVICE_NAME);
bluetoothDevice = device;
break;
}
}
}
if (bluetoothDevice == null)
Log.i("queryPairedDevices2()", "没有与目标远程端配对的信息");
}
解析:
本方法仅仅获取的已经与本设备进行配对过的设备
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
是获取本地蓝牙,这是实例化本地蓝牙适配器的必须过程bluetoothAdapter.getName()
获取本地蓝牙的名称bluetoothAdapter.isEnabled()
询问本地蓝牙是否被打开bluetoothAdapter.enable();
打开本地蓝牙,返回值布尔型,表示打开成功与否Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
获取与本地蓝牙已经配对过的远程设备(BluetoothDevice),并他们存储在set集合中(set类型是Java中一个不可以存放重复数据的集合,存放的内容也必须是引用类型而不能是基本数据类型)BluetoothDevice device : pairedDevices
在for循环中使用此方式进行遍历多用于引用数据类型,因为引用数据类型通常需要引入迭代器才能遍历,用上述方法可以简化。device.getName()和device.getAddress()
获取远程蓝牙的名字和地址
蓝牙地址的表示格式:XX:XX:XX:XX:XX:XX,X可以是数字,也可以是字母,与网络设备的MAC地址一样,就是设备之间通讯的唯一身份证(跟电脑的IP地址性质形同,唯一确认蓝牙DEVICE_NAME.equals(device.getName())
从已配对的设备中选中我们在一开始想要连接的远程蓝牙,将此蓝牙赋值给全局变量bluetoothDevice,以便在以后操作
三、重写run方法
/**
* 线程体:执行连接和读取数据
*/
@Override
public void run() {
Log.w("run()", "线程体:执行连接和读取数据");
// TODO Auto-generated method stub
try {
connect();
readData();
} catch (IOException e) {
measureResult.put("errorInfo", e.getMessage());
}
Message msg = handlerBluetooth.obtainMessage();
msg.obj = this.measureResult;
handlerBluetooth.sendMessage(msg);
Log.i("AbstractedAdapter", "run()");
/**
* 请求与服务端建立连接
*/
private void connect() {
Log.w("connect()", "请求与服务端建立连接");
// 客户端bluetoothDevice请求与Server建立连接socket
BluetoothSocket socket = null;
try {
socket = bluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID);
socket.connect();
if (socket.isConnected()) {
Log.i("connect()", "成功连接");
}
inputStream = socket.getInputStream();
} catch (IOException e) {
Log.e("connect()", "连接异常");
destory();
}
}
/**
* 读取socket上InputStream输入流数据
*/
protected void readData() throws IOException {
Log.w("read()", "开始读取socket上InputStream");
byte[] dataBuf = new byte[dataLeng];
int recTotalCount = 0;
try {
if (inputStream == null) {
destory();
return;
}
int count = 0;
while (true) {
count = inputStream.available();
Log.i("count", String.valueOf(count));
Log.i("inputStream.available()",
String.valueOf(inputStream.available()));
if (count > 0) {
int readCount = inputStream.read(dataBuf, recTotalCount,
count);
recTotalCount += readCount;
if (readCount == dataLeng) {
break;
}
} else {
Log.i("Thread.sleep(100);", "线程阻塞");
Thread.sleep(100);
}
}
}
解析: