在此我说几点蓝牙开发中一些注意事项及容易踩坑的地方,希望可以帮助到大家!!!
1.权限问题:在android6.0以后部分权限需要我们动态申请,对于蓝牙这块我们需要申请,首先我们在清单文件配置权限
其中位置权限需要我们动态申请
2.搜索-连接:在搜索以及连接这两步中我们要弄清楚是在工作线程还是主线程中操作的,另外我建议搜索的时候根据uuid去搜索,这样可以降低搜索范围,提高效率。因为蓝牙搜索本来就是一个耗时而不是很稳定的操作。
3.开启接收新数据通知:其实这是我今天重点讲解的地方,在以往我们可以通过厂商提供的协议然后找到对应服务以及服务下的特征。
var service: BluetoothGattService? = mBluetoothGatt!!.getService(serviceUuid)
?: return
var characteristic: BluetoothGattCharacteristic? = service!!.getCharacteristic(characteristicUuid)
?: return
// 开启新数据接收通知
mBluetoothGatt!!.setCharacteristicNotification(characteristic, true)
var descriptors = characteristic!!.descriptors
for (dp in descriptors) {
//设置特征的属性
dp.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
mBluetoothGatt!!.writeDescriptor(dp)
mBluetoothGatt!!.readDescriptor(dp)
}
当你一套流程走完后,其实差不多可以采集到蓝牙设备数据了。
然而在最近与鱼跃蓝牙设备通讯的时候,搜索-连接这套流程都走成功了,并且也跟上诉一样设置了新数据接收通知,可是始终无法接收蓝牙设备测量数据。我怀疑过是我代码出问题了,可是我一步步调试下来,发现没有发现什么可疑之处。于是乎我就换另外一个厂家的设备进行调试(把相应的uuid跟换下)测试结果是:这厂家的设备可以通讯及采集测量数据。这时候我懵了,我又想是不是设备出现问题了,但是如果设备出现问题为什么搜索-连接都能成功呐?最后我实在找不出哪里出现问题了,我在网上搜索了很久很久,终于找到一个作者提到相识问题了这帖子说的是蓝牙芯片nRF设置setCharacteristicNotification是不能真正打开Notify接收通知的。当我看到这里的时候我以为我能解决问题了,结果后面一句话我又懵了。
不过总归知道问题所在了,我看了下原生的Ble好像并没有其他与打开通知的api,于是我尝试了一个第三方库:FastBleLib按照官方示例写了下,
var uuids = arrayOf(UUID.fromString("00001810-0000-1000-8000-00805f9b34fb"))
//初始化
BleManager.getInstance().init(mActivity!!.application)
BleManager.getInstance()
.enableLog(true)
.setReConnectCount(3, 3000).operateTimeout = 3000
//是否支持ble
if (!BleManager.getInstance().isSupportBle) {
WindowUtils.showToast(mActivity!!, "该设备不支持蓝牙")
return
}
//判断当前蓝牙是否已经打开
if (!BleManager.getInstance().isBlueEnable) {
BleManager.getInstance().enableBluetooth()
Observable.interval(1, 1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BaseObserver {
override fun onNext(t: Any) {
super.onNext(t)
startBLE_disposable?.let {
if (BleManager.getInstance().isBlueEnable)
if (!it.isDisposed) {
it.dispose()
initScan(uuids)
}
}
}
override fun onSubscribe(d: Disposable) {
super.onSubscribe(d)
startBLE_disposable = d
}
})
} else
initScan(uuids)
}
//配置扫描规则
private fun initScan(uuid: Array) {
var bsrc = BleScanRuleConfig.Builder()
.setServiceUuids(uuid) // 只扫描指定的服务的设备,可选
.setScanTimeOut(10000) // 扫描超时时间,可选,默认10秒
.build()
BleManager.getInstance().initScanRule(bsrc)
//开始扫描
startScan()
}
//开始扫描
private fun startScan() {
BleManager.getInstance().scan(object : BleScanCallback() {
override fun onScanFinished(scanResultList: MutableList?) {
Log.e("-scan-", "扫描结束")
}
override fun onScanStarted(success: Boolean) {
Log.e("-scan-", "开始扫描")
}
override fun onScanning(bleDevice: BleDevice?) {
devices = bleDevice
//停止扫描
BleManager.getInstance().cancelScan()
//延迟100ms在操作
Observable.timer(100, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BaseObserver {
override fun onNext(t: Any) {
//开始连接
startConnect()
}
})
}
})
}
//开始链接
private fun startConnect() {
BleManager.getInstance().connect(devices, object : BleGattCallback() {
override fun onStartConnect() {
Log.e("-connect-", "开始连接")
}
override fun onDisConnected(
isActiveDisConnected: Boolean,
device: BleDevice?,
gatt: BluetoothGatt?,
status: Int
) {
BleManager.getInstance().disconnect(device)
Log.e("-connect-", "连接断开")
// //延迟100ms在操作
// Observable.interval(2, 2, TimeUnit.SECONDS)
// .take(1)
// .subscribeOn(Schedulers.io())
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe(object : BaseObserver {
// override fun onNext(t: Any) {
// Log.e("-connect-", "重新连接")
// //重新连接
// startConnect()
// }
// })
}
override fun onConnectSuccess(bleDevice: BleDevice?, gatt: BluetoothGatt?, status: Int) {
Log.e("-connect-", "连接成功并发现服务")
//延迟100ms在操作
Observable.timer(100, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BaseObserver {
override fun onNext(t: Any) {
//开启通知
Openindicate()
}
})
}
override fun onConnectFail(bleDevice: BleDevice?, exception: BleException?) {
Log.e("-连接失败-", "${exception.toString()}")
}
})
}
//开启通知
private fun Openindicate() {
BleManager.getInstance().indicate(
devices,
"00001810-0000-1000-8000-00805f9b34fb",
"00002a35-0000-1000-8000-00805f9b34fb",
object : BleIndicateCallback() {
override fun onCharacteristicChanged(data: ByteArray?) {
val sBuffer = StringBuffer()
for (i in data!!.indices) {
val s = Integer.toHexString(data[i].toInt() and 0xff)
if (s.length < 2)
sBuffer.append('0')
sBuffer.append("$s ")
}
Log.e("-result-", sBuffer.toString())
zhuan(sBuffer.toString())
}
override fun onIndicateSuccess() {
Log.e("--MSG--", "打开通知操作成功")
}
override fun onIndicateFailure(exception: BleException?) {
Log.e("--MSG--", "打开通知操作失败")
}
})
}
发现终于接收到通知了,我也不知道原生为什么不行,如果有朋友知道的请告知...
第三方库github地址:https://github.com/Jasonchenlijian/FastBle