Android蓝牙通信-2016-05-30

近来工作做了很多Android手机对接蓝牙设备的工作,记录一下。

场景

需要对接蓝牙设备,发送或者获取数据,比如蓝牙打印机、蓝牙体脂称、蓝牙电子血压计、蓝牙血糖仪、蓝牙身高尺等等。大致的过程就是手机跟设备互相连接认证,互传数据的过程。当然,对接不同的设备,会有不同的交互流程,同一类设备,针对不同厂商,也需要遵循不同厂商定制的SDK的相关协议。但都离不开蓝牙的核心协议,下面分经典蓝牙2.0以及低功耗蓝牙4.0(BLE)。

经典蓝牙2.0

比较传统的设备只支持蓝牙2.0,SPP协议、HDP协议
过程:扫描,配对,连接,通信

参考:Android 蓝牙开发基本流程

1、通用UUID:
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
2、配对,反射设置密码(如果需要设置的话)
Method removeBondMethod = btClass.getDeclaredMethod("setPin",  new Class[] { byte[].class }); 
return value = (Boolean) removeBondMethod.invoke(bluetoothDevice,  new Object[] { password.getBytes() });
3、配对,反射调用绑定方法
Method createBondMethod = btClass.getMethod("createBond");
Boolean value = (Bovolean) createBondMethod.invoke(btDevice);
4、连接,根据不同SDK方式

问题:getBluetoothService() called with no BluetoothManagerCallback

int sdk = Build.VERSION.SDK_INT;
if (sdk >= 10) {
    socket = mDevice.createInsecureRfcommSocketToServiceRecord(SPP_UUID);
} else {
    socket = mDevice.createRfcommSocketToServiceRecord(SPP_UUID);
}

低功耗蓝牙4.0技术(BLE)

注意:从Android4.3(API-18)开始支持BLE,但只支持作为中心设备模式Central,也就是只支持Android设备主动扫描连接外围设备Peripheral,在Android5.0(API-21)两种模式都支持。蓝牙4.0将三种规格集一体,包括传统蓝牙技术、高速技术和低耗能技术
参考:最全最详细的蓝牙版本介绍包含蓝牙4.0和4.1
过程:扫描,连接,发现服务,通信

1、获取BluetoothAdapter
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
2、判断是否支持蓝牙,并打开蓝牙(利用系统Intent的方式请求打开蓝牙)
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
3、搜索BLE设备
mBluetoothAdapter.startLeScan(mLeScanCallback);
BluetoothAdapter.LeScanCallback // 搜索回调

注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。
实际使用:使用经典蓝牙搜索方式startDiscovery()能同时搜索到百捷2.0和百捷4.0的设备

4、连接GATT Server
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
BluetoothGattCallback // 连接回调
5、连接成功。BluetoothGatt常规用到的几个操作示例
connect(); // 连接远程设备。
discoverServices(); // 搜索连接设备所支持的service。
disconnect(); // 断开与远程设备的GATT连接。
close(); // 关闭GATT Client端。
readCharacteristic(characteristic); // 读取指定的characteristic。
setCharacteristicNotification(characteristic, enabled); // 设置当指定characteristic值变化时,发出通知。
getServices(); // 获取远程设备所支持的services。

一些实践心得

关于蓝牙硬件

对接蓝牙设备,一方面由于蓝牙设备的多样性,另一方面Android手机硬件、系统的多样性,会遇到比较多的问题就是蓝牙连接的稳定性问题。关于这个问题也是尝试了很多种方法去避免,分析其中一个原因就是:由代码驱动蓝牙硬件的过程,需要一定的时间,一定的时间等待,会带来极大稳定性的提高。比如启动蓝牙后延迟300ms在执行其他操作。另一个就是可以采用线程轮询判断一个状态是否已经启动,比如循环5次,每隔1秒执行判断操作。

关于优化

必要时,考虑采用服务Service去获取设备的数据,或者设置单例模式。

如有错误,欢迎拍砖!

你可能感兴趣的:(Android蓝牙通信-2016-05-30)