蓝牙自动重连

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();

    }

}

 

转载

问题:

手机作为ble服务器在发现客户端后主动连接,连接失败。

现象:

在调用bluetoothDevice.connectgatt(BluetoothDevice,autoconnect,BluetoothGattCallback); 后,在BluetoothGattCallback中的onConnectionStateChange(BluetoothGatt gatt , int status , int newState)回调中 newState状态为 BluetoothProfile.STATE_DISCONNECTED

解决方式:

在onConnectionStateChange(BluetoothGatt gatt , int status , int newState)回调中打印第二个参数(status)的值。

值为0:直接调用gatt.connect()重新连接。

值不为0(值为133/257等): ①首先执行gatt.close()清除连接;

      ②然后重新调用 bluetoothDevice.connectgatt(BluetoothDevice,autoconnect,BluetoothGattCallback); 建立连接

原因分析:

值为0:不确定因素导致连接失败。不确定因素可能为信号太弱等。

值不为0:由于协议栈原因导致连接建立失败。所以清除掉连接后重新建立连接。
 

 

深圳逆时针

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值