Android 蓝牙连接类

package com.tech.idealled.ble;


import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;

import com.example.lightstrip.entity.BleData;
import com.example.lightstrip.exposed.SendCallBack;
import com.example.lightstrip.exposed.WriteCallBack;
import com.example.lightstrip.ui.connect.DeviceCallback;
import com.tech.idealled.App;
import com.tech.idealled.core.data.Agreement;
import com.tech.idealled.core.db.bean.Device;
import com.tech.idealled.core.db.dao.DeviceDao;
import com.tech.idealled.ui.home.MainActivity;
import com.tech.idealled.util.LogUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
;

/**
 * @author xiaotie
 * 2022、2、17
 * lightStrip 专用类
 */

import cn.com.heaton.blelibrary.ble.L;
import cn.com.heaton.blelibrary.ble.model.BleDevice;
import cn.com.heaton.blelibrary.ble.utils.ByteUtils;

@SuppressLint("MissingPermission")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class LightStripBleManager {

    public static final HashMap<String,BleData> devices = new HashMap<>();
    public static final HashMap<String,Runnable> runnableCallback = new HashMap<>();
    private static final LightStripBleManager instance = new LightStripBleManager();
    private final BleListenerImpl bleListener;
    private final DeviceDao deviceDao;
    private BleManager bleManager = BleManager.getInstance();
    private DeviceCallback deviceCallback;
    private BluetoothManager bluetoothManager;
    private BluetoothAdapter bluetoothAdapter;

    private static final UUID SERVICE = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");
    private static final UUID Write1 = UUID.fromString("d44bc439-abfd-45a2-b575-925416129600");
    private static final UUID Write2 = UUID.fromString("d44bc439-abfd-45a2-b575-92541612960a");
    private static final UUID Write3 = UUID.fromString("d44bc439-abfd-45a2-b575-92541612960b");
    private static final UUID Notify = UUID.fromString("d44bc439-abfd-45a2-b575-925416129601");

    private final BluetoothGattCallback bluetoothGattCallback;
    private final Handler handler = new Handler();
    private final int timeOut = 5000;
    private List<HashMap<String,List<byte[]>>> cache= new ArrayList<>();
    private List<WriteCallBack> callBacks = new ArrayList<>();
    private SendCallBack sendCallBack;

    private Runnable sendTimeOut = new Runnable() {
        @Override
        public void run() {
            if(sendCallBack!=null && cache.size()>0 && cache.get(cache.size()-1)!=null){
                for (String address:cache.get(cache.size()-1).keySet()) {
                    sendCallBack.timeOut(devices.get(address));
                };
            }
        }
    };
    private double curTime;

    private LightStripBleManager(){
        bleListener = new BleListenerImpl();
        bleManager.registerBleListener(bleListener);
        deviceDao = App.getDaoSession().getDeviceDao();
        bluetoothGattCallback = new BluetoothGattCallback() {
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                super.onConnectionStateChange(gatt, status, newState);
                BleData bleData = devices.get(gatt.getDevice().getAddress());
                //操作成功
                if(status == BluetoothGatt.GATT_SUCCESS){
                    if(bleData == null){
                        LogUtil.e( "device cache miss.");
                        return;
                    }
                    if(newState == BluetoothProfile.STATE_DISCONNECTED){
                        bleData.setConnectionState(newState);
                        if(deviceCallback != null){
                            deviceCallback.onBleData(bleData,false);
                        }
                        gatt.close();
                        devices.remove(gatt.getDevice().getAddress());
                        LogUtil.d("connectOrDis + 断开连接"+bleData.getBleAddress()+"---"+bleData.getBleName());
                    }else if(newState == BluetoothProfile.STATE_CONNECTED){
                        LogUtil.d("connectOrDis + 获取服务"+gatt.getDevice().getAddress()+"---"+gatt.getDevice().getName());
                        boolean b = bleData.getBluetoothGatt().discoverServices();
                        if(!b){
                            LogUtil.d("connectOrDis + GATT Service acquisition failed");
                            devices.remove(bleData.getBleAddress());
                            gatt.disconnect();
                            return;
                        }else {
                            runnableCallback.put(bleData.getBleAddress(), () -> {
                                LogUtil.d("connectOrDis + GATT Service No reaction");
                                devices.remove(bleData.getBleAddress());
                                gatt.disconnect();
                            });
                            handler.postDelayed(runnableCallback.get(bleData.getBleAddress()), timeOut);
                        }
                    }
                }
                if(status == 133){
                    LogUtil.d("connectOrDis + status 133");
                    devices.remove(bleData.getBleAddress());
                    gatt.disconnect();
                }
            }

            @Override
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                super.onServicesDiscovered(gatt, status);
                handler.removeCallbacks(runnableCallback.get(gatt.getDevice().getAddress()));
                LogUtil.d("connectOrDis + 设置mtu"+gatt.getDevice().getAddress()+"---"+gatt.getDevice().getName());
                gatt.requestMtu(512);
            }

            @Override
            public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                super.onCharacteristicRead(gatt, characteristic, status);
            }

            @Override
            public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                super.onCharacteristicWrite(gatt, characteristic, status);
            }

            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
                super.onCharacteristicChanged(gatt, characteristic);
                byte[] dataEd = Agreement.getDecodeData(characteristic.getValue());
                String address = gatt.getDevice().getAddress();
                               for (WriteCallBack callBack :callBacks) {
                    callBack.onCharacteristicChanged(devices.get(address),dataEd);
                }
                for (int i = 0; i < cache.size(); i++) {
                    HashMap<String,List<byte[]>> item = cache.get(i);
                    if(item.containsKey(address)){
                        List<byte[]> bytes = item.get(address);
                        String arrays = Arrays.toString(bytes.get(0));
                        String censor = arrays.substring(1, arrays.length()-1);
                        if(Arrays.toString(dataEd).contains(censor)){
                            boolean result = true;
                            if(bytes.get(1)!=null && bytes.size()<3 && bytes.get(1).length != 0){
                                result= write(gatt, bytes.get(1), Write1);
                            }else if(bytes.get(1)!=null) {
                                result = write(gatt, bytes.get(1), Write2);
                            }
                            if(!result && sendCallBack!=null){
                                sendCallBack.fail(devices.get(address));
                            }
                            bytes.remove(1);
                            if(bytes.size()<2 || bytes.get(1).length==0){
                                item.remove(address);
                                if(result){
                                    for (HashMap<String,List<byte[]>> it: cache) {
                                        result = it.get(address)==null;
                                    }
                                    if(result){
                                        sendCallBack.success(devices.get(address));
                                    }
                                }
                            }else {
                                item.put(address,bytes);
                            }
                            if(cache.get(i).size() ==0){
                                cache.remove(i);
                            }
                            if(cache.size() ==0 && sendCallBack!=null){
                                sendCallBack.successAll();
                            }
                            return;
                        }
                    }
                }
            }

            @Override
            public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
                super.onDescriptorRead(gatt, descriptor, status);
            }

            @Override
            public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
                super.onDescriptorWrite(gatt, descriptor, status);
            }

            @Override
            public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
                super.onMtuChanged(gatt, mtu, status);
                BleData bleData = devices.get(gatt.getDevice().getAddress());
                if(bleData == null){
                    LogUtil.d( "connectOrDis + device cache miss.");
                    return;
                }
                LogUtil.d("connectOrDis + 设置mtu成功"+bleData.getBleAddress()+"---"+bleData.getBleName());
                BluetoothGatt bluetoothGatt = bleData.getBluetoothGatt();
                BluetoothGattService gattService = bluetoothGatt.getService(SERVICE);
                if(gattService != null){
                    BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(Notify);
                    if(characteristic != null){
                        enableNotification(bluetoothGatt,true, characteristic);
                        LogUtil.d("connectOrDis + 更新设备"+bleData.getBleAddress()+"---"+bleData.getBleName());
                        bleData.setConnectionState(BluetoothProfile.STATE_CONNECTED);
                        if(deviceCallback != null){
                            deviceCallback.onBleData(bleData,false);
                        }
                        devices.put(bleData.getBleAddress(),bleData);
                    }else {
                        LogUtil.d("connectOrDis + Characteristic null "+bleData.getBleAddress()+"---"+bleData.getBleName());
                        gatt.disconnect();
                        devices.remove(bleData.getBleAddress());
                    }
                }else {
                    LogUtil.d("connectOrDis + GATT Service null "+bleData.getBleAddress()+"---"+bleData.getBleName());
                    gatt.disconnect();
                    devices.remove(bleData.getBleAddress());
                }

            }
        };
    }

    public void registerCallback(WriteCallBack writeCallBack){
        callBacks.add(writeCallBack);
    }

    public void unregisterCallback(WriteCallBack writeCallBack){
        callBacks.remove(writeCallBack);
    }

    /**
     *
     * @param bluetoothGatt Gatt
     * @param enable  注册(true)/注销(false)
     * @param characteristic 通知特征ID
     */
    public void enableNotification(BluetoothGatt bluetoothGatt, boolean enable, BluetoothGattCharacteristic characteristic) {
        if (bluetoothGatt == null || characteristic == null) {
            return;
        }
        if (!bluetoothGatt.setCharacteristicNotification(characteristic, enable)) {
            return;
        }
        //获取到Notify当中的Descriptor通道  然后再进行注册
        List<BluetoothGattDescriptor> clientConfigs = characteristic.getDescriptors();
        if (clientConfigs == null || clientConfigs.size() ==0) {
            return;
        }
        if (enable) {
            for (BluetoothGattDescriptor clientConfig: clientConfigs) {
                clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                boolean b = bluetoothGatt.writeDescriptor(clientConfig);
                LogUtil.d("connectOrDis + 注册通知"+b);
            }
        } else {
            for (BluetoothGattDescriptor clientConfig: clientConfigs) {
                clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
                boolean b = bluetoothGatt.writeDescriptor(clientConfig);
                LogUtil.d("connectOrDis + 注销通知"+b);
            }
        }
    }

    public static LightStripBleManager getInstance(){
        return instance;
    }

    @SuppressLint("MissingPermission")
    public void disconnectAll(){
        for (BleData bleData:devices.values()) {
            bleData.getBluetoothGatt().disconnect();
        }
    }

    public void setCallBack(DeviceCallback deviceCallback){
        this.deviceCallback = deviceCallback;
    }

    public List<BleData> getDevices() {
        return new ArrayList<>(devices.values());
    }

    private boolean write (BluetoothGatt gatt, byte[] data,UUID write) {
        BluetoothGattService gattService = gatt.getService(SERVICE);
        if(gattService==null){
            LogUtil.d("Write + GATT 服务丢失");
            return false;
        }
        BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(write);
        if(characteristic==null){
            LogUtil.d("Write + Characteristic 特征丢失");
            return false;
        }
        characteristic.setValue(data);
        return gatt.writeCharacteristic(characteristic);
    }

    public boolean write1(byte[] data) {
        boolean result = false;
        for (BleData bleData :devices.values()) {
            if(bleData.getConnectionState() == BluetoothProfile.STATE_CONNECTED){
                result = write(bleData.getBluetoothGatt(),data,Write1);
            }
        }
        return result;
    }

    /**
     * @param data 发送的数据
     * @param sendCallBack {@link SendCallBack}
     * @param list 后续要发的东西 格式:
     *             byte[0] 触动发送的条件 例:new byte[]{'X', 'I', 'A', 'Y', 'I', 'B','U'}
     *             byte[1] byte[last-1] 发送的东西(write2) 例:new byte[]{'S', J', 'Y', 'I'}
     *             byte[last] 发送结束的通知(write1) 例:new byte[]{'O', 'K'}, 不需要时可以为new byte[0]
     * @return
     */
    @SafeVarargs
    public final boolean write1(byte[] data, SendCallBack sendCallBack, List<byte[]>... list) {
        this.sendCallBack = sendCallBack;
        cache.clear();
        handler.removeCallbacks(sendTimeOut);
        handler.postDelayed(sendTimeOut,10*1000);
        boolean result = false;
        if(devices.size() ==0 ){
            if(sendCallBack!=null){
                sendCallBack.fail(null);
            }
            return false;
        }
        HashMap<String, List<byte[]>> stringHash;
        for (List<byte[]> item : list) {
            stringHash = new HashMap<>();
            for (BleData bleData : devices.values()){
                stringHash.put(bleData.getBleAddress(), new ArrayList<>(item));
            }
            cache.add(stringHash);
        }
        for (BleData bleData : devices.values()) {
            if (bleData.getConnectionState() == BluetoothProfile.STATE_CONNECTED) {
                result = write(bleData.getBluetoothGatt(), data, Write1);
                if(!result && sendCallBack!=null){
                    sendCallBack.fail(bleData);
                }
            }
        }

        return result;
    }


    public boolean write3(byte[] data) {
        boolean result = false;
        for (BleData bleData :devices.values()) {
            if(bleData.getConnectionState() == BluetoothProfile.STATE_CONNECTED){
                result = write(bleData.getBluetoothGatt(),data,Write3);
            }
        }
        return result;
    }

    public boolean write1(BluetoothGatt gatt, byte[] dataEd) {
        return write(gatt,dataEd,Write1);
    }


    class BleListenerImpl extends BleListener{

        @Override
        public boolean filterDevice(BleDevice device, int rssi, byte[] scanRecord) {
            if(!LightStripBleConfig.matchProduct(scanRecord)) {return true;}

            BleData bleData = new BleData();
            bleData.setBluetoothDevice(device.getBluetoothDevice());
            bleData.setScanRecord(scanRecord);
            bleData.setConnectionState(BluetoothProfile.STATE_DISCONNECTED);
            bleData.setBleAddress(device.getBleAddress());
            bleData.setBleName(device.getBleName());
            bleData.setOtaVersion("");
            if(deviceCallback != null){
                deviceCallback.onBleData(bleData,true);
            }
            if(isReConnect(bleData.getBleAddress())){
                if (System.currentTimeMillis() - curTime > 1500) {
                    connectOrDis(bleData);
                    curTime = System.currentTimeMillis();
                }
            }
            return super.filterDevice(device, rssi, scanRecord);
        }

        @Override
        public void onStart() {
            super.onStart();
        }

        @Override
        public void onStop() {
            super.onStop();
        }

        @Override
        public void onChanged(BleDevice device, byte[] data) {

        }
    }

    /**
     * 保存 是否可以重连地址
     *
     * @param bleName 设备名称
     * @param bleAddress 设备地址
     * @param isReConnect 是否可以重连
     */
    public void saveDevice(String bleName, String bleAddress, boolean isReConnect) {
        try {
            Device device = deviceDao.queryBuilder().where(DeviceDao.Properties.Mac.eq(bleAddress)).unique();
            if (device != null && !TextUtils.isEmpty(device.getMac())) {
                device.setDeviceName(bleName);
                device.setIsReConnect(isReConnect);
                device.setMac(bleAddress);
                deviceDao.update(device);
            } else {
                Device device1 = new Device();
                device1.setDeviceName(bleName);
                device1.setIsReConnect(isReConnect);
                device1.setMac(bleAddress);
                deviceDao.save(device1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 连接、断开设备
     *
     */

    @SuppressLint("MissingPermission")
    public void connectOrDis(BleData bleData){
        if(devices.get(bleData.getBleAddress()) == null ||
                (devices.get(bleData.getBleAddress()).getConnectionState() == bleData.getConnectionState() &&
                        devices.get(bleData.getBleAddress()).getConnectionState() != BluetoothProfile.STATE_CONNECTING &&
                        devices.get(bleData.getBleAddress()).getConnectionState() != BluetoothProfile.STATE_DISCONNECTING)
        ){}else {return;}
        LogUtil.d("connectOrDis + 操作中"+bleData.getBleAddress()+"---"+bleData.getBleName()+"---"+bleData.getConnectionState());
        //检查蓝牙地址
        if(!BluetoothAdapter.checkBluetoothAddress(bleData.getBleAddress())){
            LogUtil.e( "checkBluetoothAddress False");
            return;
        }
        //断开设备
        if(bleData.getConnectionState() == BluetoothProfile.STATE_CONNECTED){
            LogUtil.d("connectOrDis + 断开设备"+bleData.getBleAddress()+"---"+bleData.getBleName());
            bleData.getBluetoothGatt().disconnect();
            bleData.setConnectionState(BluetoothProfile.STATE_DISCONNECTING);
            runnableCallback.put(bleData.getBleAddress(), () -> {
                LogUtil.d("connectOrDis + GATT Service No reaction");
                devices.remove(bleData.getBleAddress());
            });
            devices.put(bleData.getBleAddress(),bleData);
            return;
        }
        //连接设备
        if (bluetoothManager == null) {
            bluetoothManager = (BluetoothManager) App.getContext().getSystemService(Context.BLUETOOTH_SERVICE);
            if (bluetoothManager == null) {
                LogUtil.e( "Unable to initBLE BluetoothManager.");
                return;
            }
        }
        if (bluetoothAdapter == null) {
            bluetoothAdapter = bluetoothManager.getAdapter();
            if (bluetoothAdapter == null) {
                LogUtil.e( "Unable to obtain a BluetoothAdapter.");
                return;
            }
        }
        LogUtil.d("connectOrDis + 获取设备"+bleData.getBleAddress()+"---"+bleData.getBleName());
        BluetoothDevice device = bluetoothAdapter.getRemoteDevice(bleData.getBleAddress());
        LogUtil.d("connectOrDis + 保存设备"+bleData.getBleAddress()+"---"+bleData.getBleName());
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//            //GATT连接到远程双模设备优先BLE
//            bleData.setBluetoothGatt(device.connectGatt(App.getContext(), false, bluetoothGattCallback, BluetoothDevice.TRANSPORT_LE));
//        }else {
        bleData.setBluetoothGatt(device.connectGatt(App.getContext(), false, bluetoothGattCallback));
//        }
        bleData.setConnectionState(BluetoothProfile.STATE_CONNECTING);
        devices.put(bleData.getBleAddress(),bleData);
    }


    /**
     * 是否可以重连
     *
     * @param bleAddress 设备地址
     * @return 是否可以重连
     */
    private boolean isReConnect(String bleAddress) {
        try {
            if (!TextUtils.isEmpty(bleAddress)) {
                Device device = deviceDao.queryBuilder().where(DeviceDao.Properties.Mac.eq(bleAddress)).unique();
                if (device != null) {
                    return device.getIsReConnect();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值