欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android:BLE蓝牙开发

程序员文章站 2024-03-24 22:01:22
...

一、发现蓝牙设备:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                        mBleAdapter.startLeScan(mOldScanCallback);
                    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        mBleAdapter.getBluetoothLeScanner().startScan(mNewScanCallback);
                    }


二、根据系统版本号处理不同的回调:

**
     * 4.3及以上-5.0以下版本蓝牙搜索回调
     */
    private BluetoothAdapter.LeScanCallback mOldScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {

            String adress = "...";
            stopLeScan();
            connectGatt(adress);
        }
    };

    /**
     * 5.0及以上版本蓝牙搜索回调
     */
    private ScanCallback mNewScanCallback = new ScanCallback() {

        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                
                String adress = "...";
                stopLeScan();
                connectGatt(adress);
            }
        }

    };

三、连接蓝牙设备:

/**
     * 连接蓝牙设备
     *
     * @param address 蓝牙设备的地址
     * @return true: 成功  false: 失败
     */
    public boolean connectGatt(String address) {
        if (mBleAdapter == null) {
            return false;
        }
        BluetoothDevice device = mBleAdapter.getRemoteDevice(address);
        if (device == null) {
            return false;
        }
        BluetoothGatt gatt = device.connectGatt(mContext, false, mGattCallback);
        if (gatt != null) {
            mGattMap.put(address, gatt);
            return true;
        }
        return false;
    }

四、处理连接回调:

/**
     * 各种状态回调
     */
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

        /**
         * 连接或断开时触发
         * @param gatt 用于发现服务与处理数据的对象
         * @param status 判断连接或断开执行是否成功,BluetoothGatt.GATT_SUCCESS表示成功
         * @param newState 判断连接状态,BluetoothProfile.STATE_CONNECTED为连接,BluetoothProfile.STATE_DISCONNECTED为断开
         */
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, final int status, final int newState) {
            String address = gatt.getDevice().getAddress();
            if (status != BluetoothGatt.GATT_SUCCESS) {
                disconnect(address);
                return;
            }
            /*
            连接成功, 调用discoverServices发现服务
             */
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                if (mGattMap.get(address) == null) {
                    return;
                }
                gatt.discoverServices();
                return;
            }
            /*
            连接断开, 从原列表中移除BluetoothGatt
             */
            if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                disconnect(address);
            }
        }

        /**
         * 发现了服务时触发
         * @param gatt 用于发现服务与处理数据的对象
         * @param status 判断发现服务执行是否成功,BluetoothGatt.GATT_SUCCESS表示成功
         */
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, final int status) {
            String address = gatt.getDevice().getAddress();
            if (status != BluetoothGatt.GATT_SUCCESS) {
                disconnect(address);
                return;
            }
            if (!setCanReceiverData(address, gatt)) {
                return;
            }
            mConnected = true;
            if (mListener != null) {
                mListener.onConnected();
            }
        }

        /**
         * 调用BluetoothGatt.writeDescriptor方法设置通知方式后触发,
         * @param gatt 用于发现服务与处理数据的对象
         * @param descriptor 写通知方式时传输的数据对象
         * @param status 判断writeDescriptor是否执行成功,BluetoothGatt.GATT_SUCCESS表示成功
         */
        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, final int status) {
            if (status != BluetoothGatt.GATT_SUCCESS) {
                disconnect(gatt.getDevice().getAddress());
                return;
            }
        }

        /**
         * 蓝牙设备主动向手机发送数据时触发
         * @param gatt 用于发现服务与处理数据的对象
         * @param characteristic 特征值对象
         */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            if (mListener == null) {
                return;
            }
            mListener.onReceiver(characteristic.getValue());
        }

        /**
         * 手机向蓝牙设备写数据后回调
         * @param gatt 用于发现服务与处理数据的对象
         * @param characteristic 特征值对象
         * @param status 写数据是否成功,BluetoothGatt.GATT_SUCCESS表示成功
         */
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            if (mListener == null) {
                return;
            }
            boolean isSuccess = true;
            if (status != BluetoothGatt.GATT_SUCCESS) {
                isSuccess = false;
            }
            mListener.onWrite(isSuccess);
        }
    };

    /**
     * 设置手机可接收蓝牙设备发过来的数据
     *
     * @param address 蓝牙设备地址
     * @param gatt    用于发现服务与处理数据的对象
     */
    private boolean setCanReceiverData(String address, BluetoothGatt gatt) {
        if (mGattMap.get(address) == null) {
            return false;
        }

        BluetoothGattService service = gatt.getService(UUIDConfig.SERVICE_UUID);
        if (service == null) {
            disconnect(address);
            return false;
        }

        List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
        for (BluetoothGattCharacteristic characteristic : characteristics) {
            if (UUIDConfig.CHARACTERISTIC_UUID.equals(characteristic.getUuid().toString())) {
                mCharacteristicMap.put(address, characteristic);
            } else if (characteristic.getProperties() == BluetoothGattCharacteristic.PROPERTY_NOTIFY) {
                return writeDescriptor(gatt, characteristic);
            }
        }
        return true;
    }

    /**
     * 设置蓝牙设备主动往手机写数据的方式,即通知方式
     */
    private boolean writeDescriptor(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        // 设置手机能接收蓝牙设备发来的数据,有主动数据时,onCharacteristicChanged方法触发
        gatt.setCharacteristicNotification(characteristic, true);

        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUIDConfig.DESCRIPTOR_UUID);
        if (descriptor == null) {
            return false;
        }
        int properties = characteristic.getProperties();
        byte[] value = null;
        if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
            //有可通知属性notify的设置方式
            value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
        } else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
            //有indecation属性的设置方式
            value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;
        }
        if (value == null) {
            return false;
        }
        descriptor.setValue(value);
        //会触发onDescriptorWrite方法
        gatt.writeDescriptor(descriptor);
        return true;
    }

五、读写方法、以及关闭连接等方法:

/**
     * 主动读取蓝牙设备的数据
     *
     * @param address 蓝牙设备地址
     */
    public void readData(String address) {
        if (mGattMap.get(address) == null || mCharacteristicMap.get(address) == null) {
            onRead(false);
            return;
        }
        boolean state = mGattMap.get(address).readCharacteristic(mCharacteristicMap.get(address));
        if (!state) {
            onRead(false);
        }
    }

    /**
     * 主动向蓝牙设备写数据
     *
     * @param address 蓝牙设备地址
     * @param data    数据
     */
    public void wirteData(String address, byte[] data) {
        if (mGattMap.get(address) == null || mCharacteristicMap.get(address) == null) {
            onWrite(false);
            return;
        }
        BluetoothGattCharacteristic gattCharacteristic = mCharacteristicMap.get(address);
        gattCharacteristic.setValue(data);
        boolean state = mGattMap.get(address).writeCharacteristic(gattCharacteristic);
        if (!state) {
            onWrite(false);
        }
    }

    /**
     * 断开连接
     *
     * @param address 蓝牙设备地址
     */
    public void disconnect(String address) {
        if (mGattMap.get(address) == null) {
            return;
        }
        mGattMap.get(address).disconnect();
        mGattMap.remove(address);
        if (mCharacteristicMap.get(address) == null) {
            return;
        }
        mCharacteristicMap.remove(address);
    }