Android 一连多很多坑啊。
不同的手机反响不一样;双外设的应用。
第一版,按正常逻辑进行连接,正常,可以工作;测试后,发现偶尔设备完全连不上了。
设备丢了。
修改第二版,只要有设备处于连接时,不进行其他设备连接;第二版,在一些手机上稳定运行。
扩大测试了,某些手机出问题,发现偶尔设备完全连不上了。
网上百度文章:
看了这一篇文章,发现里面的重点:
Android连接多蓝牙设备ble 并发通讯小框架 --Android连接多ble蓝牙设备--Android与多ble蓝牙设备连接 - 老凯瑞 - 博客园
(二)Android APP与蓝牙多设备连接注意的点:
1、设备一个一个连,连接成功一个再一个,如果同时连多个,可能一个都连不上。具体原因没有深究
2、如果一个设备被你连过,然后一系列操作后,无法再扫描到,用其他工具APP也扫描不到,说明这个设备被你连着,没有彻底的释放掉!如何完全释放ble,具体看源码,其中部分我也是参考了网上著名的蓝牙框架 fastble:https://www.jianshu.com/p/795bb0a08beb ,感谢作者
3、对APP对ble的每一步操作间,必须加延时,否则会有意想不到的问题。具体看源码
4、ble被断开后,必须延时1-2秒,再去连接他(不通过扫描直接连的情况),否则会有意想不到的问题
5. 注意对mBluetoothLeScanner操作,存在多线程的操作的时候,记得加锁。不然可能出现意想不到的溢出,多次开关软件/扫描后;蓝牙不能扫描了等意想不到的结果。
6. 注意对mBluetoothGatt操作,存在多线程的操作的时候,记得加锁。 不然可能导致影响其他蓝牙设备或是蓝牙底层。
原来问题出在这里,修改第三版:
连接前,关闭广播,等连接成功或失败回调,或超时才打开广播。
一个一个连接。
现在扩大测试样本。
修改第四版:
第三版每次都能连接上,但会出现连接超时,导致有时连接时长超过30s以上。
修改:
connect不要在扫描回调中调用,回调打开设备后,暂停扫描,延时1S以上时间,再开始连接。初步测试了7个型号手机,没有出现问题。2个连接时,时间基本稳定在20S以内。
另外在连接前Gatt.close掉,并设置为null;最好是清一下缓存,网上有相关文章。另外请注意连接时和断连后,必须要的延时不能去掉;去掉一样会出错。比较容易出现的问题是,手机显示是未连接,但设备显示已连接;重点手机断不开,要重启设备。
定时广播函数:
private void startRescanTimer() {
if(mTimerReScan!=null)
{
mTimerReScan.cancel();
mTimerReScan=null;
}
mTimerReScan = new Timer();
if(mTimerReScanTask!=null) {
mTimerReScanTask.cancel();
mTimerReScanTask=null;
}
mTimerReScanTask=new TimerTask() {
// static boolean blScanOldStatus = true;
@Override
public void run() {
// TODO Auto-generated method stub
if(mBluetoothLeScanner==null)
{
BleReadyStartScan();
return;
}
if (mRingFitBleWithoutScan[0].isConnected() && mRingFitBleWithoutScan[1].isConnected()) {
// Log.v("Scan", "kill rescan task,because dev is connected");
// if(mBluetoothAdapter.isDiscovering()==true)
{
scanLeDevice(false);
}
//m_i32BleOpDelay=0;
//blScanOldStatus = false;
// mTimerReScan.cancel();
//mTimerReScan=null;
//mTimerReScanTask.cancel();
//mTimerReScanTask=null;
return;
}
if(mblConnectAsk)
{
m_iConnectAskDelayCnt++;
if(m_iConnectAskDelayCnt>1)
{
Connect2Device();
}
}
//如果有设备在连接中,不要使能扫描
//if((mRingFitBleWithoutScan[0].isConnecting()==false)&&(mRingFitBleWithoutScan[1].isConnecting()==false))
{
m_i32BleOpDelay++;
if (m_i32BleOpDelay > 7*2) {
m_i32BleOpDelay = 0;
if (m_blScanning == false) {
Log.v("Scan", "scan is stop ,rescan again");
m_blScanning = true;
/* if((mRingFitBleWithoutScan[0].isConnected()==false)&&(mRingFitBleWithoutScan[1].isConnected()==false))
{
mBluetoothAdapter.disable();
mBluetoothAdapter.enable();
}*/
scanLeDevice(false);
scanLeDevice(true);
} else {
m_blScanning = false;
Log.v("Scan", "the phone is scanning");
}
}
}
}
};
mTimerReScan.schedule(mTimerReScanTask
, 0,500);
}
打描回调函数:
private ScanCallback mLeScanCallback =
new ScanCallback () {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
//boolean blConnecting=false;
//m_blScanning = true;
if (result == null || result.getDevice() == null
) {
Log.v("Scan", "No Find device by Scan");
return;
} else {
BluetoothDevice device = result.getDevice();
String deviceName = device.getName();
String ConDevName = com.dfjy.libdemoui.RingGattAttributes.DEV_NAME;//"DFJY_R001";
Log.v(TAG, "Ble Name:" + deviceName);
if (deviceName != null) {
if((mRingFitBleWithoutScan[0].isConnecting()==false)&&(mRingFitBleWithoutScan[1].isConnecting()==false))
{
if (deviceName.contains("DFJY_R00")) {
scanLeDevice(false);
m_i32BleOpDelay=0;
mblConnectAsk=true;
mStrConnectName = deviceName;
mStrConnectMac=device.getAddress();
m_iConnectAskDelayCnt=0;
} else {
Log.v("ScanDFJY Dev", "已找到设备:" + deviceName + "\tMAC:" + device.getAddress());
}
}
if(mRingFitBleWithoutScan[0].isConnected()&&mRingFitBleWithoutScan[1].isConnected())
{
scanLeDevice(false);
}
}
else
{
Log.v("ScanDFJY Dev", "已找到设备:" + deviceName + "\tMAC:" + device.getAddress());
}
}
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
scanLeDevice(false);
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};