蓝牙自动重连

1利用系统中的自动重连

getDevice().connectGatt(context, autoConnect, coreGattCallback);

private BleGattCallback coreGattCallback = new BleGattCallback() {
    @Override
public void onDisConnected(BluetoothGatt gatt, int status, BleException exception) {
    BleLog.i("BleGattCallback:onConnectFailure ");

    if(null != gatt && tryConnectCount > 0 && !isClosed){
        tryConnectCount --;
        if(gatt.connect()) {
            onDisConnected2Reconnect(gatt, status, exception);
            return ;
        }
    }

    closeBluetoothGatt();
    bluetoothGatt = null;
    Iterator iterator = callbackHashMap.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry entry = (Map.Entry) iterator.next();
        Object call = entry.getValue();
        if (call instanceof BleGattCallback) {
            ((BleGattCallback) call).onDisConnected(gatt, status, exception);
        }
    }
}
}
/**
 * Connect back to remote device.
 *
 * <p>This method is used to re-connect to a remote device after the
 * connection has been dropped. If the device is not in range, the
 * re-connection will be triggered once the device is back in range.
 *
 * @return true, if the connection attempt was initiated successfully
 */
public boolean connect() {
    try {
        mService.clientConnect(mClientIf, mDevice.getAddress(),
                               false, mTransport); // autoConnect is inverse of "isDirect"
        return true;
    } catch (RemoteException e) {
        Log.e(TAG,"",e);
        return false;
    }
}

 2 另外自己控制重连,https://bbs.csdn.net/topics/391008501

public  class  BluetoothMain {
 
     private  boolean  isConnected =  false ;
     private  volatile  boolean  hasDataToSend =  false ;
     private  volatile  boolean  hasDataToReceive =  false ;
     private  boolean  isScaning =  false ;
     private  boolean  isNeedConnect =  false ;                      // 用在回调函数中,当连接状态断开后,判断是否是正常断开还是需要重连
 
     private  HandlerThread handlerThread =  null ;
     private  Handler handler =  null ;
     private  Runnable runnable =  null ;
 
     // XXX 关于定时器和计数器的时间计数设置需要重新设定
     private  Counter dataTransferCounter =  null ;
     private  Counter readCounter =  null ;                      // this counter is to process read failed so many times
     private  Counter writeAfterReadCounter =  null ;              // this counter is to process write failed so many times after successful read
     private  Counter ackConfirmCounter =  null ;                  // this counter is to prevent infinitely read characteristic after writing an ack
     private  java.util.Timer timer =  null ;                     // 主要用于连接失败时进行尝试
 
     private  BluetoothManager bleManager =  null ;
     private  BluetoothAdapter mAdapter =  null ;
     private  BluetoothAdapter.LeScanCallback mLeScanCallback =  null ;
     private  BluetoothGattCallback gattCallback =  null ;
     private  BluetoothGatt bluetoothGatt =  null ;
 
     private  Context context =  null ;
     private  BLECallback bleCallback =  null ;
 
     private  byte  bleRssi =  0 ;
     private  byte  scanCount =  0 ;
     private  byte  connectCount =  0 ;
     private  short  postTime =  0 ;
     
     private  static  final  boolean  DBG =  true
     private  static  final  String BLUETOOTH_INFO =  "bluetoothComm" ;
 
     public  BluetoothMain(Context context, List<String> deviceUUIDList, BLECallback bleCb) {
         this .context = context;
         bleCallback = bleCb;
 
         bleUUIDList = deviceUUIDList;
 
         bleManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
         mAdapter = bleManager.getAdapter();
 
         deviceFoundSet =  new  HashSet<String>();
         deviceLoseMap =  new  ConcurrentHashMap<String, Boolean>();
         deviceInControlSet =  new  HashSet<String>();
 
         activeDevices =  new  HashSet<String>();
         sleepDevices =  new  HashSet<String>();
         
         dataSendUuidQueue =  new  HashMap<String, Queue< byte []>>();
 
         mLeScanCallback =  new  LeScanCallback() {
             @Override
             public  void  onLeScan(BluetoothDevice device,  int  rssi,  byte [] scanRecord) {
                 bleRssi = ( byte ) rssi;
                 String bleAddress = device.getAddress();
                 String deviceUUID = FrameUtility.convertMACToUUID(bleAddress);
                 if  (scanRecord[ 7 ] == GattConstants.ADVERTISE_TYPE_SLEEP){   // 判断设备是否是处于休眠状态,然后更新设备所在的集合(活跃设备、休眠设备)
                     if  ( activeDevices.contains(deviceUUID)){
                         activeDevices.remove(deviceUUID);
                     }
                     sleepDevices.add(deviceUUID);
                 else  {
                     if  ( sleepDevices.contains(deviceUUID)){
                         sleepDevices.remove(deviceUUID);
                     }
                     activeDevices.add(deviceUUID);
                     // 小节点处于活跃状态
                     if  (scanRecord[ 7 ] == GattConstants.ADVERTISE_TYPE_COMMON) {
                         // 小节点没有数据发送,根据deviceUUID查看dataSendUUIDList中是否有数据需要发送
                         if  (dataSendUuidQueue.get(deviceUUID) !=  null  && dataSendUuidQueue.get(deviceUUID).size() >  0 ){
                             if  (firstScanToSend) {
                                 firstScanToSend =  false ;
                                 hasDataToSend =  true ;
                                 connect(bleAddress);
                             }
                         }
                     else  if  (scanRecord[ 7 ] == GattConstants.ADVERTISE_TYPE_DATA) {
                         // 小节点有数据需要发送
                         if  (firstScanToReceive) {
                             firstScanToReceive =  false ;
                             connect(bleAddress);
                         }
                    
                 }
             }
         };
 
         gattCallback =  new  BluetoothGattCallback() {
             @Override
             public  void  onConnectionStateChange(BluetoothGatt gatt,  int  status,  int  newState) {
                 super .onConnectionStateChange(gatt, status, newState);
                 if (status == BluetoothGatt.GATT_SUCCESS){
                     if (DBG){Log.d(BLUETOOTH_INFO,  "onConnectionStateChange ---> operation success" );}
                     if  (newState == BluetoothGatt.STATE_DISCONNECTED) {
                         if  (!isConnected) {
                             if  (!isNeedConnect) {
                                 // 正常断开
                                 if (DBG){Log.d(BLUETOOTH_INFO,  "onConnectionStateChange ---> disconnected" );}
                             }
                         else  {
                             // 意外断开后直接断开,不尝试重连
                             if (DBG){Log.d(BLUETOOTH_INFO,  "onConnectionStateChange ---> disconnected acidentally" );}
                             isConnected =  false ;
                             firstScanToSend =  true ;
                             firstScanToReceive =  true ;
                         }
                         if  (bluetoothGatt !=  null ){
                             bluetoothGatt.close();  // 释放资源
                             bluetoothGatt =  null ;
                         }
                         //断开连接,开始扫描。经测试,不能直接调用startSearch(),否则会有10s的延时。
                         //另外,若立即开始扫描的话,由于蓝牙节点的广播切换需要时间,可能还会扫描到"02"广播包,导致不必要的连接。
                         handler.postDelayed(runnable,  400 );
                     else  if  (newState == BluetoothGatt.STATE_CONNECTED) {
                         isConnected =  true ;
                         isNeedConnect =  false ;
                         
                         if  (timer !=  null ){
                             timer.cancel();
                             timer =  null ;
                         }
                          // 进行服务发现,50ms
                         try  {
                             Thread.sleep( 50 );
                         catch  (Exception e) {
                             e.printStackTrace();
                         }
                         gatt.discoverServices();
                     }
                 else  {
                     if (DBG){Log.d(BLUETOOTH_INFO,  "onConnectionStateChange ---> operation failure" );}
                 }
             }
 
             @Override
             public  void  onServicesDiscovered( final  BluetoothGatt gatt,  int  status) {
                 super .onServicesDiscovered(gatt, status);
                 BluetoothGattService service = gatt.getService(UUID.fromString(GattConstants.SERVICE_UUID));
                 BluetoothGattCharacteristic readCharacteristic_2 = service.getCharacteristic(UUID.fromString(GattConstants.CHARACTERISTIC_READ_UUID_2));
                 gatt.readCharacteristic(readCharacteristic_2);
             }
 
             @Override
             public  void  onCharacteristicRead( final  BluetoothGatt gatt,  final  BluetoothGattCharacteristic characteristic,  int  status) {
                 super .onCharacteristicRead(gatt, characteristic, status);
                 byte [] data = characteristic.getValue();
                 BluetoothGattService service = gatt.getService(UUID.fromString(GattConstants.SERVICE_UUID));
                 BluetoothGattCharacteristic writeCharacteristic_1 = service.getCharacteristic(UUID.fromString(GattConstants.CHARACTERISTIC_WRITE_UUID_1));
                 final  String deviceUuid = FrameUtility.convertMACToUUID(gatt.getDevice().getAddress());
                 // 手机向小节点发送数据是通过写特征值1来实现的,当小节点读取完数据之后,将特征值设为全1
                 if  (characteristic.equals(writeCharacteristic_1)) {
                     // 读特征值1操作成功
                     if  (status == BluetoothGatt.GATT_SUCCESS) {
                         // 小节点读取完毕,关闭超时计数器,继续发送下一个数据
                         if  (isArrayEqual(data, GattConstants.FrameInfo.ALL_ONE_RSP.getBytes())) {
                             if  (readCounter !=  null ) {
                                 readCounter.close();
                                 readCounter =  null ;
                             }
                             dataSendUuidQueue.get(deviceUuid).poll();
                             sendNextPacket();
                         else  {
                             // 小节点未将数据取走,计数器加1
                             if  (readCounter ==  null ) {
                                 // 连续读取10次失败之后,断开连接,回到初始状态
                                 readCounter =  new  Counter( 10 "readCounter" new  CounterTask() {
                                     @Override
                                     public  void  run() {
                                         readCounter.close();
                                         readCounter =  null ;
                                         // sendNextPacket();
                                         dataSendUuidQueue.get(deviceUuid).poll();     //由于PC和服务器端存在重传机制,超时之后删除当前数据包,并断开连接
                                         disconnect();
                                     }
                                 });
                                 readCounter.start();
                             }
                             readCounter.addCount();
                             if  (readCounter.getCount() <= readCounter.getMaxCount()) {
                                 gatt.readCharacteristic(characteristic);
                             }
                         }
                     else  {
                         // CQ:实验中测试,程序到达这里之后,连接会断开然后自动重新连接
                         if (DBG){Log.d(BLUETOOTH_INFO,  "onCharacteristicRead status---> failed" );}
                     }
                 else  {
                     // 读特征值2(用于小节点向手机发送数据)
                     if  (status == BluetoothGatt.GATT_SUCCESS) {
                         // 如果读到的数据为全0,表示小节点没有数据要发送
                         if  (isArrayEqual(data, GattConstants.FrameInfo.ALL_ZERO_RSP.getBytes())) {
                             // XXX 不使用计数器,若没有数据则直接断开
                             if  (ackConfirmCounter !=  null ) {
                                 ackConfirmCounter.close();
                                 ackConfirmCounter =  null ;
                             }
                             hasDataToReceive =  false ;
                             if  (hasDataToSend) {
                                 sendNextPacket();
                             else  {
                                 // 手机没有数据要发送
                                 disconnect();
                             }
                         else  if  (isArrayEqual(data, GattConstants.FrameInfo.ALL_ONE_RSP.getBytes())) {
                             hasDataToReceive =  false ;
                             if  (hasDataToSend) {
                                 sendNextPacket();
                             else  {
                                 // 手机没有数据要发送
                                 if (DBG){Log.d(BLUETOOTH_INFO,  "disconnect ---> no data to send" );}
                                 disconnect();
                             }
                         else  {
                             // 小节点有数据发送过来
                             if  (ackConfirmCounter !=  null ) {
                                 ackConfirmCounter.close();
                                 ackConfirmCounter =  null ;
                             }
                             hasDataToReceive =  true ;
                             if  (data[GattConstants.FrameInfo.FRAME_HEX_MAX_LEN] ==  '1' ) {
                                 // 最后一个字节为'1',表示小节点还有数据需要发送
                                 characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                                 characteristic.setValue(GattConstants.FrameInfo.ALL_ONE_RSP.getBytes());
                                 gatt.writeCharacteristic(characteristic);
                             else  if  (data[GattConstants.FrameInfo.FRAME_HEX_MAX_LEN] ==  '0' ) {
                                 // 最后一个字节为'0',表示小节点没有数据需要发送
                                 hasDataToReceive =  false ;
                                 // CQ:读完最后一个数据包之后,将特征值全部置0,表示这一个阶段结束
                                 characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                                 characteristic.setValue(GattConstants.FrameInfo.ALL_ZERO_RSP.getBytes());
                                 gatt.writeCharacteristic(characteristic);
                             }
                             // 对读取到的数据包进行转义,然后调用回调接口向上层发送数据
                             String uuid = FrameUtility.convertMACToUUID(bluetoothGatt.getDevice().getAddress());
                             byte [] dataToServer = FrameUtility.decodeFrame(data,  true , uuid.getBytes(),( byte )-bleRssi);
                             //printData(dataToServer, "data to server");
                             bleCallback.dataReceivedCb(dataToServer);
                         }
                     }
                 }
             }


  @Override
             public  void  onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,  int  status) {
                 super .onCharacteristicWrite(gatt, characteristic, status);
                 byte [] data = characteristic.getValue();
                 printData(data,  "onCharacteristicWrite" );
                 BluetoothGattService service = gatt.getService(UUID.fromString(GattConstants.SERVICE_UUID));
                 BluetoothGattCharacteristic writeCharacteristic_1 = service.getCharacteristic(UUID.fromString(GattConstants.CHARACTERISTIC_WRITE_UUID_1));
                 if  (characteristic.equals(writeCharacteristic_1)) {
                     // CQ:手机利用特征值1向小节点发送数据
                     if  (status == BluetoothGatt.GATT_SUCCESS) {
                         // CQ:写操作成功,关闭并清空超时计数器
                         if  (dataTransferCounter !=  null ) {
                             dataTransferCounter.close();
                             dataTransferCounter =  null ;
                         }
                         // 等待100ms,读取特征值,看小节点是否读取完毕
                         try  {
                             Thread.sleep( 100 );
                         catch  (Exception e) {
                             e.printStackTrace();
                         }
                         gatt.readCharacteristic(characteristic);  // 读取特征值看小节点是否读取完毕
                     else  {
                         // 计数器加1,重新发送该数据包
                         dataTransferCounter.addCount();
                         if  (dataTransferCounter.getCount() <= dataTransferCounter.getMaxCount()){
                             gatt.writeCharacteristic(characteristic);
                         }
                     }
                 else  {
                     // 对特征值2进行写操作(用于提示小节点,手机已读取完数据包)
                     if  (status == BluetoothGatt.GATT_SUCCESS) {
                         if  (writeAfterReadCounter !=  null ) {
                             writeAfterReadCounter.close();
                             writeAfterReadCounter =  null ;
                         }
                         // 等待100ms之后再读取
                         try  {
                             Thread.sleep( 100 );
                         catch  (InterruptedException e) {
                             e.printStackTrace();
                         }
                         // 再读取特征值2,确认写操作成功,然后断开连接
                         gatt.readCharacteristic(characteristic);
                     else  {
                         if (DBG){Log.d(BLUETOOTH_INFO,  "onCharacteristicWrite:status---> failed" );}
                         // 写失败之后,开启超时计数器,超时之后直接断开连接
                         if  (writeAfterReadCounter ==  null ) {
                             writeAfterReadCounter =  new  Counter( 10 "writeAfterReadCounter" new  CounterTask() {
                                 @Override
                                 public  void  run() {
                                     writeAfterReadCounter =  null ;
                                     hasDataToReceive =  false ;
                                     disconnect();
                                 }
                             });
                             writeAfterReadCounter.start();
                         }
                         writeAfterReadCounter.addCount();
                         if  (writeAfterReadCounter.getCount() <= writeAfterReadCounter.getMaxCount()) {
                             characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                             // 根据hasDataToReceive标志位,写全1或全0
                             if  (hasDataToReceive) {
                                 characteristic.setValue(GattConstants.FrameInfo.ALL_ONE_RSP.getBytes());
                             else  {
                                 characteristic.setValue(GattConstants.FrameInfo.ALL_ZERO_RSP.getBytes());
                             }
                             gatt.writeCharacteristic(characteristic);
                         }
                     }
                 }
 
             }
         };
 
         // 使用handlerThread线程处理handler的消息队列,而不直接使用handler
         handlerThread =  new  HandlerThread( "scan thread" );
         handlerThread.start();
         handler =  new  Handler(handlerThread.getLooper());
         runnable =  new  Runnable() {
             @Override
             public  void  run() {
                 startSearch();
             }
         };
         startSearch();
     }
 
     @SuppressWarnings ( "deprecation" )
     public  void  startSearch() {
         // 检查蓝牙设备是否开启
         if  (!mAdapter.isEnabled()) {
             mAdapter.enable();
         }
         
          // 如果正在扫描,则停止扫描,然后重新开始扫描.若持续扫描的话,只会收到设备的第一条广播包
         if  (isScaning) {
             isScaning =  false ;
             mAdapter.stopLeScan(mLeScanCallback);
             postTime = ( short )( 0.5  * GattConstants.POST_PERIOD);
         else  {
             // 采用UUID方式进行设备过滤存在问题,不使用mAdapter.startLeScan(serviceUuids, callback)该方法
             isScaning =  true ;
             mAdapter.startLeScan(mLeScanCallback);
             postTime = GattConstants.POST_PERIOD;
         }
         handler.postDelayed(runnable, postTime);
     }
 
     // 官方Demo使用address作为参数
     @SuppressWarnings ( "deprecation" )
     private  void  connect(String bleAddress) {
         if  (!isConnected) {
             handler.removeCallbacks(runnable);
             if  (isScaning) {
                 isScaning =  false ;
                 mAdapter.stopLeScan(mLeScanCallback);
             }
             // 主要用在连接状态改变回调函数中,当断开连接时,用于判定是否真正需要断开连接,和连接失败进行区分
             isNeedConnect =  true ;
             
             BluetoothDevice device = mAdapter.getRemoteDevice(bleAddress);
             bluetoothGatt = device.connectGatt(context,  false , gattCallback);
             
         }
     }
 
     private  void  disconnect() {
         if  (bluetoothGatt ==  null ) {
             return ;
         }
         isConnected =  false ;
         firstScanToSend =  true ;
         firstScanToReceive =  true ;
          // close和disconnect的区别: close除了断开连接外,还会释放掉所有资源,导致不可以直接在后面的操作中用gatt对象的connect直接连接, 
          //                            而disconnect并不释放资源 ,所以,所有的资源还保存着,就可以用Gatt的connect进行简单恢复连接,
          //                            而不是在device那一层进行操作
         // 调用disconnect断开连接,然后在回调函数中使用close()释放资源
         bluetoothGatt.disconnect();
     }
}


猜你喜欢

转载自blog.csdn.net/long13631/article/details/80754133