一、应用背景
本文介绍的事例,使用android蓝牙连接远程蓝牙(益体康电子血压计),将血压计采集到高压、低压、心率数据解析后通过蓝牙连接传入android端处理。程序为项目节选,依工程形式打包发布到此,能完整运行,附送源码,希望能对有需要的朋友们有所帮助。
二、流程说明
三、主要源代码
(1)、public class MainActivity extends Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
// 数据处理handler
handler = new BloodPressureHandler(this);
// 本地蓝牙操作线程bluetoothDeviceAdapter实现Runnalbe接口
bluetoothDeviceAdapter = new BluetoothDeviceAdapter(this, handler);
// 启动线程完成蓝牙相关操作:开启、搜索发现、查询配对设备信息、建立与目标设备的连接、进行数据传输、释放连接等
new Thread(bluetoothDeviceAdapter).start();
}
(2)、public class BluetoothDeviceAdapter implements Runnable
/**
*
* @name 蓝牙操作线程
* @descripation 完成蓝牙相关操作:开启、搜索发现、查询配对设备信息、建立与目标设备的连接、进行数据传输、释放连接等
* @author Freedoman
* @date 2014-3-22
* @version 1.0
*/
@SuppressLint("NewApi")
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 = "BP:HC-503B";
/**
* 构造方法:获取本地蓝牙实例,打开蓝牙,搜索设备信息,查询已配对的设备
*
* @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 registerAndDiscover() {
Log.w("registerScan()", "注册广播事件并准备扫描发现周边设备");
bluetoothReceiver = new BluetoothReciever();
IntentFilter infilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(bluetoothReceiver, infilter);
if (bluetoothAdapter.startDiscovery()) {
Log.i("bluetoothAdapter", "开始扫描");
}
}
/**
* 查询已配对的设备
*/
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()", "没有与目标远程端配对的信息");
}
/**
* 线程体:执行连接和读取数据
*/
@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);
}
}
// 解析到高压、低压、心率数据
String strTemp = this.parseData(dataBuf);
String highBloodMeasure = Integer.valueOf(strTemp.substring(4, 8),
16).toString();
String lowBloodMeasure = Integer.valueOf(strTemp.substring(8, 10),
16).toString();
String pulseRate = Integer.valueOf(strTemp.substring(10, 12), 16)
.toString();
Log.i("测量到的高压数据", highBloodMeasure);
Log.i("测量到的低压数据", lowBloodMeasure);
Log.i("测量到的心率", pulseRate);
measureResult.put("highBloodMeasure", highBloodMeasure);
measureResult.put("lowBloodMeasure", lowBloodMeasure);
measureResult.put("pulseRate", pulseRate);
} catch (IOException e) {
e.printStackTrace();
throw new IOException("蓝牙数据传送异常!");
} catch (InterruptedException e) {
e.printStackTrace();
throw new IOException("未知异常,建议重启程序!");
} finally {
destory();
}
}
/**
* 解析byte[]中的字节流到字符串cs中
*
* @param bs
* @return
*/
private String parseData(byte[] bs) {
Log.i("parseData()", "---");
char[] cs = new char[bs.length];
for (int i = 0; i < bs.length; i++) {
cs[i] = (char) bs[i];
}
return new String(cs);
}
/**
* 关闭输入输出流,释放连接,关闭蓝牙
*/
protected void destory() {
Log.w("destory()", "关闭输入输出流,释放连接,关闭蓝牙");
try {
if (inputStream != null) {
inputStream.close();
inputStream = null;
}
if (outputStream != null) {
outputStream.close();
outputStream = null;
}
if (socket != null) {
socket.close();
socket = null;
}
/*
* if (bluetoothAdapter != null) { bluetoothAdapter.disable(); }
*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
(3)、public class BluetoothReciever extends BroadcastReceiver
/**
*
* @name 接收查找到的蓝牙设备信息的广播
* @descripation 注册一个BroadcastReceiver的ACTION_FOUND对象,通过Filter来过滤ACTION_FOUND这个
* Intent动作以获取每个远程设备的详细信息,通过Intent字段EXTRA_DEVICE 和
* EXTRA_CLASS可以获得包含了每个BluetoothDevice 对象和对象的该设备类型 BluetoothClass
* @author 樊俊彬
* @date 2014-3-22
* @version 1.0
*/
public class BluetoothReciever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.w("onReceive()", "发现设备...");
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.i("设备名称", device.getName());
Log.i("设备地址", device.getAddress());
}
}
}
(4)、public class BloodPressureHandler extends Handler
/**
*
* @name 按消息处理数据
* @descripation BluetoothHC503
* @author 樊俊彬
* @date 2014-3-22
* @version 1.0
*/
public class BloodPressureHandler extends Handler {
private Context context;
private EditText txtHighBlood; // 血压(mmHg)1
private EditText txtLowBlood; // 血压(mmHg)2
private EditText txtRate; // 心率
public BloodPressureHandler(Context context){
this.context = context;
}
public void handleMessage(Message msg) {
//把消息上携带的obj给Map<> bluetoothMeasureData
Map<String, String> bluetoothMeasureData = (Map) msg.obj;
if (bluetoothMeasureData == null || bluetoothMeasureData.isEmpty())
return;
String errorInfo = bluetoothMeasureData.get("errorInfo");
Log.i("测量到的高压数据", bluetoothMeasureData.get("highBloodMeasure"));
Log.i("测量到的低压数据", bluetoothMeasureData.get("lowBloodMeasure"));
Log.i("测量到的心率", bluetoothMeasureData.get("pulseRate"));
Log.i("错误信息", bluetoothMeasureData.get("errorInfo"));
}
}
四、血压计设备相关参数说明
五、附送源码