Android ble从机模式(ble Server)

本文是Android作为ble server端,启动APP后直接启动server,等待client来连接。
废话不多说,直接上代码:

APP启动后调用初始化:

BleServerInstance.getInstance().open()

退出APP的时候:

override fun onDestroy() {
        super.onDestroy()
        BleServerInstance.getInstance().closeBle()
    }

BleServerInstance.java

public class BleServerInstance {

    private static int HEAD1 = 0x3A;
    private static int HEAD2 = 0xA3;
    private static int HEAD_5B = 0x5B;
    private static int HEAD_B3 = 0xB3;
    private static int CMD_01 = 0x01;
    private static int CMD_02 = 0x02;
    private List<Byte> mBytes = new ArrayList<>();
    private UUID UUID_SERVER = UUID.fromString("000000ff-0000-1000-8000-00805f9b34fb");
    private UUID UUID_DESCRIPTOR = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    private UUID UUID_CHARWRITE = UUID.fromString("0000ff01-0000-1000-8000-00805f9b34fb");

    private static String BLE_NAME = "BLE_NAME";

    private BlePeripheralUtils blePeripheralUtils;

    private BlePeripheralCallback callback = new BlePeripheralCallback() {
        @Override
        public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
            LiveDataBus.get().with(LiveDataConstants.BLE_CONNECT_STATES).postValue(newState);
            if (newState == 2){
                blePeripheralUtils.stopBluetoothLeAdvertiser();
            }
        }

        @Override
        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes) {
            String ble = ByteUtil.hexBytesToString(requestBytes).trim();
            Log.i("lala", "======onCharacteristicChanged==========>" + ble);
            receiveData(requestBytes);
        }

        @Override
        public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
//            blePeripheralUtils.notify("5aa2".getBytes(),UUID_SERVER,UUID_CHARWRITE);
            LiveDataBus.get().with(LiveDataConstants.BLE_READ).postValue("");
        }
    };

    public BleServerInstance() {
        initBle();
    }

    public static BleServerInstance getInstance() {
        return BleManagerHolder.sBleManager;
    }

    private static class BleManagerHolder {
        private static final BleServerInstance sBleManager = new BleServerInstance();
    }

    public void initBle() {
        //实例化工具类
        blePeripheralUtils = new BlePeripheralUtils(App.instance);
        //初始化一下
        blePeripheralUtils.init();
        //设置一个结果callback 方便把某些结果传到前面来
        blePeripheralUtils.setBlePeripheralCallback(callback);

        //实例化需要添加的service信息
        BluetoothGattCharacteristicInfo[] bluetoothGattCharacteristicInfos = new BluetoothGattCharacteristicInfo[1];
        BluetoothGattDescriptorInfo descriptorInfo = new BluetoothGattDescriptorInfo(UUID_DESCRIPTOR, BluetoothGattCharacteristic.PERMISSION_WRITE);
        bluetoothGattCharacteristicInfos[0] = new BluetoothGattCharacteristicInfo(UUID_CHARWRITE,
                BluetoothGattCharacteristic.PROPERTY_NOTIFY
                        | BluetoothGattCharacteristic.PROPERTY_READ
                        | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE,
                BluetoothGattCharacteristic.PROPERTY_NOTIFY
                        | BluetoothGattCharacteristic.PERMISSION_READ
                        | BluetoothGattCharacteristic.PERMISSION_WRITE,
                descriptorInfo);

        BluetoothGattServiceInfo bluetoothGattServiceInfo1 = new BluetoothGattServiceInfo(UUID_SERVER, BluetoothGattService.SERVICE_TYPE_PRIMARY,bluetoothGattCharacteristicInfos);
        //添加需要的service
        blePeripheralUtils.addServices(bluetoothGattServiceInfo1);
    }

    public void closeBle() {
        blePeripheralUtils.stopBluetoothLeAdvertiser();
        blePeripheralUtils.toDisable();
    }

    public void open() {
        //先打开广播
        blePeripheralUtils.startBluetoothLeAdvertiser(BLE_NAME);
    }

    /**
     * 解析 ble data
     *
     * @param data
     */
    private void receiveData(byte[] data) {
        //先按照5bb3协议解析,如果解析不对再继续往下走,否则return
        List<Byte> datas = Bytes.asList(data);
        if (data[0] == (byte) HEAD_5B && data[1] == (byte) HEAD_B3 && judgeByte(datas)){
            //视为蓝牙名字通讯
            analysisBleNameData(data);
            return;
        }
        if (data.length >= 2 && data[0] == (byte) HEAD1 && data[1] == (byte) HEAD2) {
            mBytes.clear();
        }
        mBytes.addAll(Bytes.asList(data));
//        Log.i("haha", "======mBytes==========>" + mBytes.toString());
        if (mBytes.get(2) == (byte) CMD_01 && mBytes.size() == mBytes.get(3)) {//接收特定的指令号 长度
            if (judgeByte(mBytes)) {
//                Log.e("haha", "======和校验通过==========");
                analysisBleData(mBytes);
                mBytes.clear();
            } else {
                mBytes.clear();
            }
        } else if (mBytes.get(2) == (byte) CMD_02 && mBytes.size() == mBytes.get(3)) {//接收特定的指令号 长度
            if (judgeByte(mBytes)) {
                analysisBleDataSetting(mBytes);
                mBytes.clear();
            } else {
                mBytes.clear();
            }
        } else {
            mBytes.clear();
        }
    }

    /**
     * 解析ble setting 数据
     * @param list
     */
    private void analysisBleDataSetting(List<Byte> list) {
        byte[] dataByte = Bytes.toArray(list);
        int Left_torque = dataByte[5] & 0xFF;
        int Right_torque = dataByte[6] & 0xFF;
        int Left_aim_pos = dataByte[7] & 0xFF;
        int Right_aim_pos = dataByte[8] & 0xFF;

        int Left_leg_fp_stat_H = dataByte[9]&0xFF;
        String left_H = Integer.toBinaryString(Left_leg_fp_stat_H);
        left_H = String.format("%08d", Long.parseLong(left_H));
        int Left_leg_fp_stat_L = dataByte[10]&0xFF;
        String left_L = Integer.toBinaryString(Left_leg_fp_stat_L);
        left_L = String.format("%08d", Long.parseLong(left_L));

        int Right_leg_fp_stat_H = dataByte[11]&0xFF;
        String right_H = Integer.toBinaryString(Right_leg_fp_stat_H);
        right_H = String.format("%08d", Long.parseLong(right_H));
        int Right_leg_fp_stat_L = dataByte[12]&0xFF;
        String right_L = Integer.toBinaryString(Right_leg_fp_stat_L);
        right_L = String.format("%08d", Long.parseLong(right_L));

        int Left_leg_groy = dataByte[13] & 0xFF;
        int Right_leg_groy = dataByte[14] & 0xFF;

        int Auto_send_switch = dataByte[15] & 0xFF;

        BleDataSettingBean dataSettingBean = new BleDataSettingBean(String.valueOf(Left_torque),String.valueOf(Right_torque),String.valueOf(Left_aim_pos),
                String.valueOf(Right_aim_pos), left_H,left_L,right_H,right_L,
                String.valueOf(Left_leg_groy),String.valueOf(Right_leg_groy),String.valueOf(Auto_send_switch));
        LiveDataBus.get().with(LiveDataConstants.BLE_SETTING_DATA).postValue(dataSettingBean);
    }

    /**
     * 足底蓝牙名字设置数据解析
     * @param data
     */
    private void analysisBleNameData(byte[] data) {
        int bleNameStatus = data[4];
        byte[] datum = new byte[8];
        for (int i = 0; i < 8; i++) {
            datum[i] = data[i+5];
        }
        String mac = ByteUtil.hexBytesToString(datum);
        StringBuffer buffer = new StringBuffer();
        buffer.append(ByteUtil.hexToString(mac.substring(0,2)));
        buffer.append(ByteUtil.hexToString(mac.substring(2,4)));
        buffer.append(ByteUtil.hexToString(mac.substring(4,6)));
        buffer.append(ByteUtil.hexToString(mac.substring(6,8)));

        buffer.append(ByteUtil.hexToString(mac.substring(8,10)));
        buffer.append(ByteUtil.hexToString(mac.substring(10,12)));
        buffer.append(ByteUtil.hexToString(mac.substring(12,14)));
        buffer.append(ByteUtil.hexToString(mac.substring(14,16)));
        Log.e("lala", "======ble mac==========>" + buffer.toString());
        BleNameBean bean = new BleNameBean(bleNameStatus,buffer.toString().trim());
        LiveDataBus.get().with(LiveDataConstants.BLE_NAME_READ).postValue(bean);
    }

    /**
     * 解析数据
     * @param data
     */
    private void analysisBleData(List<Byte> data) {
//        List<Byte> bleData = data.subList(4, data.size() - 2);
//        if (bleData.size() < 56) {
//            return;
//        }
        byte[] dataByte = Bytes.toArray(data);
        int sys_mode = dataByte[4] & 0xFF;
//        Log.i("lala","====sys_mode==>"+ sys_mode);
        int sys_fault_H = dataByte[5];
        int sys_fault_L = dataByte[6];
//        Log.i("lala","====sys_fault_H==>"+ sys_fault_H);
//        Log.i("lala","====sys_fault_L==>"+ sys_fault_L);
        int sys_fault = ((sys_fault_H << 8)) | (sys_fault_L & 0xFF);
//        Log.i("lala","====ands==>"+ sys_fault);
        String sys_fault_data = Integer.toBinaryString(sys_fault);
//        Log.i("lala","====sys_fault_data==>"+ sys_fault_data);
        int save_state = dataByte[7] & 0xFF;
//        Log.i("lala","====save_state==>"+ save_state);
        int Left_knee_pos_H = dataByte[8];
        int Left_knee_pos_L = dataByte[9];
        int Left_knee_pos = ((Left_knee_pos_H << 8)) | (Left_knee_pos_L);
//        Log.i("lala","====Left_knee_pos==>"+ Left_knee_pos);
        int Right_knee_pos_H = dataByte[10];
        int Right_knee_pos_L = dataByte[11];
        int Right_knee_pos = ((Right_knee_pos_H << 8)) | (Right_knee_pos_L);
//        Log.i("lala","====Right_knee_pos==>"+ Right_knee_pos);
        int left_leg_groy = dataByte[12];
        int right_leg_groy = dataByte[13];
//        Log.i("lala","====Left_leg_groy==>"+ Left_leg_groy);
//        Log.i("lala","====Right_leg_groy==>"+ Right_leg_groy);

        int Left_leg_fp_max_H = dataByte[14];
        int Left_leg_fp_max_L = dataByte[15];
        int left_leg_fp_max = (Left_leg_fp_max_H << 8) | Left_leg_fp_max_L & 0xFF;
        Log.i("lala","====Left_leg_fp_max==>"+ left_leg_fp_max);

        int Right_leg_fp_max_H = dataByte[16];
        int Right_leg_fp_max_L = dataByte[17];
        int right_leg_fp_max = (Right_leg_fp_max_H << 8) | Right_leg_fp_max_L & 0xFF;
        Log.i("lala","====Right_leg_fp_max==>"+ right_leg_fp_max);

        int Left_leg_fp_sum_H = dataByte[18];
        int Left_leg_fp_sum_L = dataByte[19];
        int Left_leg_fp_sum = (Left_leg_fp_sum_H << 8) | Left_leg_fp_sum_L & 0xFF;
        Log.i("lala","====Left_leg_fp_sum==>"+ Left_leg_fp_sum);

        int Right_leg_fp_sum_H = dataByte[20];
        int Right_leg_fp_sum_L = dataByte[21];
        int Right_leg_fp_sum = (Right_leg_fp_sum_H << 8) | Right_leg_fp_sum_L & 0xFF;
        Log.i("lala","====Right_leg_fp_sum==>"+ Right_leg_fp_sum);

        int left_leg_fp_1 = dataByte[22] & 0xff;
        int left_leg_fp_2 = dataByte[23] & 0xff;
        int left_leg_fp_3 = dataByte[24] & 0xff;
        int left_leg_fp_4 = dataByte[25] & 0xff;
        int left_leg_fp_5 = dataByte[26] & 0xff;
        int left_leg_fp_6 = dataByte[27] & 0xff;
        int left_leg_fp_7 = dataByte[28] & 0xff;
        int left_leg_fp_8 = dataByte[29] & 0xff;
        int left_leg_fp_9 = dataByte[30] & 0xff;
        int left_leg_fp_10 = dataByte[31] & 0xff;
        int left_leg_fp_11 = dataByte[32] & 0xff;
        int left_leg_fp_12 = dataByte[33] & 0xff;
        int left_leg_fp_13 = dataByte[34] & 0xff;
        int left_leg_fp_14 = dataByte[35] & 0xff;
        int left_leg_fp_15 = dataByte[36] & 0xff;
        int left_leg_fp_16 = dataByte[37] & 0xff;
//        Log.i("lala","====left_leg_fp==>"+ left_leg_fp_1 + "==" + left_leg_fp_2 + "=="
//                + left_leg_fp_3 + "==" + left_leg_fp_4 + "=="
//                + left_leg_fp_5 + "==" + left_leg_fp_6 + "=="
//                + left_leg_fp_7 + "==" + left_leg_fp_8 + "=="
//                + left_leg_fp_9 + "==" + left_leg_fp_10 + "=="
//                + left_leg_fp_11 + "==" + left_leg_fp_12 + "=="
//                + left_leg_fp_13 + "==" + left_leg_fp_14 + "=="
//                + left_leg_fp_15 + "==" + left_leg_fp_16);

        int right_leg_fp_1 = dataByte[38] & 0xff;
        int right_leg_fp_2 = dataByte[39] & 0xff;
        int right_leg_fp_3 = dataByte[40] & 0xff;
        int right_leg_fp_4 = dataByte[41] & 0xff;
        int right_leg_fp_5 = dataByte[42] & 0xff;
        int right_leg_fp_6 = dataByte[43] & 0xff;
        int right_leg_fp_7 = dataByte[44] & 0xff;
        int right_leg_fp_8 = dataByte[45] & 0xff;
        int right_leg_fp_9 = dataByte[46] & 0xff;
        int right_leg_fp_10 = dataByte[47] & 0xff;
        int right_leg_fp_11 = dataByte[48] & 0xff;
        int right_leg_fp_12 = dataByte[49] & 0xff;
        int right_leg_fp_13 = dataByte[50] & 0xff;
        int right_leg_fp_14 = dataByte[51] & 0xff;
        int right_leg_fp_15 = dataByte[52] & 0xff;
        int right_leg_fp_16 = dataByte[53] & 0xff;
//        Log.i("lala","====right_leg_fp==>"+ right_leg_fp_1 + "==" + right_leg_fp_2 + "=="
//                + right_leg_fp_3 + "==" + right_leg_fp_4 + "=="
//                + right_leg_fp_5 + "==" + right_leg_fp_6 + "=="
//                + right_leg_fp_7 + "==" + right_leg_fp_8 + "=="
//                + right_leg_fp_9 + "==" + right_leg_fp_10 + "=="
//                + right_leg_fp_11 + "==" + right_leg_fp_12 + "=="
//                + right_leg_fp_13 + "==" + right_leg_fp_14 + "=="
//                + right_leg_fp_15 + "==" + right_leg_fp_16);
        StringBuffer leftPosData = new StringBuffer();
        leftPosData.append(left_leg_fp_1);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_2);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_3);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_4);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_5);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_6);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_7);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_8);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_9);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_10);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_11);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_12);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_13);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_14);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_15);
        leftPosData.append(",");
        leftPosData.append(left_leg_fp_16);
        StringBuffer rightPosData = new StringBuffer();
        rightPosData.append(right_leg_fp_1);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_2);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_3);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_4);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_5);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_6);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_7);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_8);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_9);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_10);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_11);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_12);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_13);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_14);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_15);
        rightPosData.append(",");
        rightPosData.append(right_leg_fp_16);

        int Left_leg_fp_stat_H = dataByte[54];
        String left_H = Integer.toBinaryString(Left_leg_fp_stat_H);
        int Left_leg_fp_stat_L = dataByte[55];
        String left_L = Integer.toBinaryString(Left_leg_fp_stat_L);
        int Right_leg_fp_stat_H = dataByte[56];
        String right_H = Integer.toBinaryString(Right_leg_fp_stat_H);
        int Right_leg_fp_stat_L = dataByte[57];
        String right_L = Integer.toBinaryString(Right_leg_fp_stat_L);

        int Auto_send_switch_stat = dataByte[58];

        BleDataBean bleDataBean = new BleDataBean(String.valueOf(sys_mode),sys_fault_data,String.valueOf(save_state),String.valueOf(Left_knee_pos),
                String.valueOf(Right_knee_pos),String.valueOf(left_leg_groy),String.valueOf(right_leg_groy),String.valueOf(left_leg_fp_max),
                String.valueOf(right_leg_fp_max),String.valueOf(Left_leg_fp_sum),String.valueOf(Right_leg_fp_sum),
                String.valueOf(left_leg_fp_1),String.valueOf(left_leg_fp_2),String.valueOf(left_leg_fp_3),
                String.valueOf(left_leg_fp_4),String.valueOf(left_leg_fp_5),String.valueOf(left_leg_fp_6),
                String.valueOf(left_leg_fp_7),String.valueOf(left_leg_fp_8),String.valueOf(left_leg_fp_9),
                String.valueOf(left_leg_fp_10),String.valueOf(left_leg_fp_11),String.valueOf(left_leg_fp_12),
                String.valueOf(left_leg_fp_13),String.valueOf(left_leg_fp_14),String.valueOf(left_leg_fp_15),
                String.valueOf(left_leg_fp_16), String.valueOf(right_leg_fp_1),String.valueOf(right_leg_fp_2),
                String.valueOf(right_leg_fp_3),String.valueOf(right_leg_fp_4),String.valueOf(right_leg_fp_5),
                String.valueOf(right_leg_fp_6),String.valueOf(right_leg_fp_7),String.valueOf(right_leg_fp_8),
                String.valueOf(right_leg_fp_9),String.valueOf(right_leg_fp_10),String.valueOf(right_leg_fp_11),
                String.valueOf(right_leg_fp_12),String.valueOf(right_leg_fp_13),String.valueOf(right_leg_fp_14),
                String.valueOf(right_leg_fp_15),String.valueOf(right_leg_fp_16),left_H,left_L,right_H,right_L,String.valueOf(Auto_send_switch_stat));

        LiveDataBus.get().with(LiveDataConstants.BLE_DATA).postValue(bleDataBean);
    }

    /**
     * 判断是否符合校验
     * 和校验、与校验
     * @param data
     * @return
     */
    private boolean judgeByte(List<Byte> data) {
        ReentrantLock lock = new ReentrantLock();
        lock.lock();
        int and =0;
        try {
            for (int i = 0; i < data.size() - 2; i++) {
                and = and + (data.get(i) & 0xff);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        int ands = ((data.get(data.size() - 2)) << 8) | (data.get(data.size() - 1) & 0xFF);
        if (ands == and) {
            return true;
        }
        return false;
    }

    /**
     * 包装要发送的数据
     * @param valueByteList
     * @return
     */
    private byte[] build(List<Byte> valueByteList,byte cmd) {
        int payloadLength = 0;
        if (valueByteList != null && valueByteList.size() > 0) {
            payloadLength = valueByteList.size();
        }
        int length = payloadLength + 6 + 5;//后边5代表5个备用0
        byte[] typeArray = new byte[length];
        int indexOfTypeArray = 0;
        typeArray[indexOfTypeArray++] = (byte) HEAD1;
        typeArray[indexOfTypeArray++] = (byte) HEAD2;
        typeArray[indexOfTypeArray++] = cmd;
        if (valueByteList != null && valueByteList.size() > 0) {
            typeArray[indexOfTypeArray++] = (byte)length;
            for (int i = 0; i < valueByteList.size(); i++) {
                typeArray[indexOfTypeArray++] = valueByteList.get(i);
            }
        }
        for (int i = 0; i < 5; i++) {
            typeArray[indexOfTypeArray++] = 0x00;
        }
        int sum = 0;
        for (byte b : typeArray) {
            sum += b & 0xFF;
        }
        byte high = (byte) ((sum >> 8) & 0xFF);
        byte low = (byte) (sum & 0xFF);
        typeArray[indexOfTypeArray++] = high;
        typeArray[indexOfTypeArray++] = low;
        return typeArray;
    }


    /**
     * 查询设备数据
     *
     */
    public void sendData(List<Byte> bleData) {
        ArrayList<Byte> array = new ArrayList<>();
        array.add(0, (byte) 0X01);
        array.addAll(bleData);
        byte[] data = build(array, (byte) CMD_01);
        Log.i("lala","===send==>"+  Arrays.toString(data));
        blePeripheralUtils.notify(data,UUID_SERVER,UUID_CHARWRITE);
//        blePeripheralUtils.notify("app data".getBytes(),UUID_SERVER,UUID_CHARWRITE);
    }

    public void querySettingData() {
        ArrayList<Byte> array = new ArrayList<>();
        array.add(0, (byte) 0X01);
        for (int i = 0; i < 11; i++) {
            array.add((byte)0X00);
        }
        byte[] data = build(array, (byte) CMD_02);
        Log.i("lala","===querySettingData==>"+  Arrays.toString(data));
        blePeripheralUtils.notify(data,UUID_SERVER,UUID_CHARWRITE);
//        blePeripheralUtils.notify("app data".getBytes(),UUID_SERVER,UUID_CHARWRITE);
    }

    /**
     * 查询或者写入ble name
     * @param type  0:查询 1:写入
     * @param data
     */
    public void queryOrWriteBleName(int type,List<String> data) {
        byte[] typeArray = new byte[15];
        int indexOfTypeArray = 0;
        typeArray[indexOfTypeArray++] = (byte) HEAD_5B;
        typeArray[indexOfTypeArray++] = (byte) HEAD_B3;
        typeArray[indexOfTypeArray++] = 0x0F;
        typeArray[indexOfTypeArray++] = 0x01;//指令号

        if (type == 0){
            typeArray[indexOfTypeArray++] = 0x00;
            for (int i = 0; i < 8; i++) {
                typeArray[indexOfTypeArray++] = 0x00;
            }
        } else {
            typeArray[indexOfTypeArray++] = 0x01;
            //写Mac,字符串转十六进制
            if (data != null && data.size() == 2){
                String left = data.get(0);
                String right = data.get(1);
                byte[] leftBytes = left.getBytes(StandardCharsets.US_ASCII);
                for (int i = 0; i < leftBytes.length; i++) {
                    typeArray[indexOfTypeArray++] = leftBytes[i];
                }
                byte[] rightBytes = right.getBytes(StandardCharsets.US_ASCII);
                for (int i = 0; i < rightBytes.length; i++) {
                    typeArray[indexOfTypeArray++] = rightBytes[i];
                }
            }
        }
        int sum = 0;
        for (byte b : typeArray) {
            sum += b & 0xFF;
        }
        byte high = (byte) ((sum >> 8) & 0xFF);
        byte low = (byte) (sum & 0xFF);
        typeArray[indexOfTypeArray++] = high;
        typeArray[indexOfTypeArray++] = low;
        Log.i("lala","===queryBleName==>"+  Arrays.toString(typeArray));
        String ble = ByteUtil.hexBytesToString(typeArray).trim();
        Log.i("lala", "====queryBleName==onCharacteristicChanged==========>" + ble);
        blePeripheralUtils.notify(typeArray,UUID_SERVER,UUID_CHARWRITE);
    }
}

1、BlePeripheralUtils.java

public class BlePeripheralUtils {
    private static final String TAG = "BlePeripheralUtils";

    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothManager bluetoothManager;
    private Context context;
    private BluetoothLeAdvertiser bluetoothLeAdvertiser;
    private BluetoothGattServer bluetoothGattServer;

    //连接上的设备
    private BluetoothDevice bluetoothDevice;
    //ble的状态callback
    private BlePeripheralCallback blePeripheralCallback;

    /**
     * 开启广播的结果callback
     */
    private AdvertiseCallback callback = new AdvertiseCallback() {

        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            Log.d(TAG, "BLE advertisement added successfully");
        }

        @Override
        public void onStartFailure(int errorCode) {
            Log.e(TAG, "Failed to add BLE advertisement, reason: " + errorCode);
        }
    };

    public BlePeripheralUtils(Context context) {
        this.context = context;
    }

    /**
     * 服务事件的回调
     */
    private BluetoothGattServerCallback bluetoothGattServerCallback = new BluetoothGattServerCallback() {

        /**
         * 1.连接状态发生变化时
         * @param device :连接的设备
         * @param status :操作状态(0是成功,其他值为失败)
         * @param newState :当前连接状态(2是已连接 0是已断开)
         */
        @Override
        public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
            Log.e(TAG, String.format("1.onConnectionStateChange:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("1.onConnectionStateChange:status = %s, newState =%s ", status, newState));

            if (newState == 2) {
                //连接成功后保存当前的设备
                bluetoothDevice = device;
                bluetoothGattServer.connect(bluetoothDevice,false);
            } else {
                //断开后从连接的列表里删除设备
                bluetoothDevice = null;
//                int index = 0;
//                for (int i = 0; i < deviceArrayList.size(); i++) {
//                    if (deviceArrayList.get(i).getAddress().equals(device.getAddress())) {
//                        index = i;
//                        break;
//                    }
//                }
//                deviceArrayList.remove(index);
            }
            //通过回调发送出去
            if (blePeripheralCallback != null) {
                blePeripheralCallback.onConnectionStateChange(device, status, newState);
            }
            super.onConnectionStateChange(device, status, newState);
        }

        @Override
        public void onServiceAdded(int status, BluetoothGattService service) {
            super.onServiceAdded(status, service);
            Log.e(TAG, String.format("onServiceAdded:status = %s", status));
        }

        @Override
        public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
            Log.e(TAG, String.format("onCharacteristicReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("onCharacteristicReadRequest:requestId = %s, offset = %s", requestId, offset));

            bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
            if (blePeripheralCallback != null) {
                blePeripheralCallback.onCharacteristicReadRequest(device, requestId, offset, characteristic);
            }
//            super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
        }


        /**
         * 3. onCharacteristicWriteRequest,接收具体的字节
         * @param device :连接的设备
         * @param requestId :请求的ID(也可以理解为流水号)
         * @param characteristic :发送消息使用的characteristic
         * @param preparedWrite :是否需要等待后续操作
         * @param responseNeeded :是否需要回复
         * @param offset : 数据内容偏移
         * @param requestBytes :数据内容
         */
        @Override
        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes) {
            Log.e(TAG, String.format("3.onCharacteristicWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("3.onCharacteristicWriteRequest:requestId = %s, preparedWrite=%s, responseNeeded=%s, offset=%s, value=%s", requestId, preparedWrite, responseNeeded, offset, new String(requestBytes)));
            bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
            //通过回调发送出去
            if (blePeripheralCallback != null) {
                blePeripheralCallback.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, requestBytes);
            }
        }

        /**
         * 2.描述被写入时,在这里执行 bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS...  收,触发 onCharacteristicWriteRequest
         * @param device
         * @param requestId
         * @param descriptor
         * @param preparedWrite
         * @param responseNeeded
         * @param offset
         * @param value
         */
        @Override
        public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
            Log.e(TAG, String.format("2.onDescriptorWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("2.onDescriptorWriteRequest:requestId = %s, preparedWrite = %s, responseNeeded = %s, offset = %s, value = %s,", requestId, preparedWrite, responseNeeded, offset, new String(value)));

            // now tell the connected device that this was all successfull
            bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
        }

        /**
         * 5.特征被读取。当回复响应成功后,客户端会读取然后触发本方法
         * @param device
         * @param requestId
         * @param offset
         * @param descriptor
         */
        @Override
        public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
            Log.e(TAG, String.format("onDescriptorReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("onDescriptorReadRequest:requestId = %s", requestId));
//            super.onDescriptorReadRequest(device, requestId, offset, descriptor);
            bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);
        }

        @Override
        public void onNotificationSent(BluetoothDevice device, int status) {
            super.onNotificationSent(device, status);
            Log.e(TAG, String.format("5.onNotificationSent:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("5.onNotificationSent:status = %s", status));
        }

        @Override
        public void onMtuChanged(BluetoothDevice device, int mtu) {
            super.onMtuChanged(device, mtu);
            Log.e(TAG, String.format("onMtuChanged:mtu = %s", mtu));
        }

        @Override
        public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
            super.onExecuteWrite(device, requestId, execute);
            Log.e(TAG, String.format("onExecuteWrite:requestId = %s", requestId));
        }
    };

    /**
     * 初始化
     */
    public void init() {
        bluetoothManager =
                (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        // Ensures Bluetooth is available on the device and it is enabled.  If not,
        // displays a dialog requesting user permission to enable Bluetooth.
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            toEnable();
        }
    }


    /**
     * 打开蓝牙
     */
    private boolean toEnable() {

        boolean result = false;
        try {
            if (mBluetoothAdapter == null) {
                return false;
            }
            for (Method temp : Class.forName(mBluetoothAdapter.getClass().getName()).getMethods()) {
                if (temp.getName().equals("enableNoAutoConnect")) {
                    result = (boolean) temp.invoke(mBluetoothAdapter);
                }
            }
        } catch (Exception e) {
            //反射调用失败就启动通过enable()启动;
            result = mBluetoothAdapter.enable();
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 关闭蓝牙
     */
    public void toDisable() {
        if (bluetoothDevice != null){
            bluetoothGattServer.cancelConnection(bluetoothDevice);
        }
        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.disable();
        }
    }

    /**
     * 开启广播
     *
     * @param bleName:ble设备的名称
     */
    public void startBluetoothLeAdvertiser(String bleName) {
        //广播设置
        AdvertiseSettings settings = new AdvertiseSettings.Builder()
                .setConnectable(true) //是否被连接
                .setTimeout(0)        //超时时间
                .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)  //广播模式
                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)   //发射功率
                .build();

        //广播数据设置
        AdvertiseData advertiseData = new AdvertiseData.Builder()
                .setIncludeDeviceName(true)    //是否在广播中携带设备的名称
                .setIncludeTxPowerLevel(true)  //是否在广播中携带信号强度
                .build();
        //扫描回应的广播设置
//        AdvertiseData scanResponseData = new AdvertiseData.Builder()
//                .setIncludeTxPowerLevel(true)  //是否在广播中携带设备的名称
//                .addServiceData(new ParcelUuid(parcelUUID), serviceData) //在scanrecord中添加的数据
//                .build();

        //设置BLE设备的名称
        mBluetoothAdapter.setName(bleName);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //开启广播
                BluetoothLeAdvertiser bluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
                bluetoothLeAdvertiser.startAdvertising(settings, advertiseData, callback);
            }
        },1000);
        //开启广播
//        BluetoothLeAdvertiser bluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
//        bluetoothLeAdvertiser.startAdvertising(settings, advertiseData, callback);
    }

    /**
     * 停止广播
     */
    public void stopBluetoothLeAdvertiser() {
        bluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
        bluetoothLeAdvertiser.stopAdvertising(callback);
    }

    /**
     * 添加ble的service
     *
     * @param serviceInfo:需要添加服务列表
     */
    public void addServices(BluetoothGattServiceInfo... serviceInfo) {
        //先获取GattServer
        bluetoothGattServer = bluetoothManager.openGattServer(context, bluetoothGattServerCallback);
        //循环添加需要添加的service
        for (BluetoothGattServiceInfo temp : serviceInfo) {
            //实例化一个service
            BluetoothGattService service_temp = new BluetoothGattService(temp.getUuid(), temp.getServiceType());
            //添加其中需要的Characteristic
            for (BluetoothGattCharacteristicInfo temp_CharacteristicInfo : temp.getCharacteristicInfos()) {
                //实例化需要的characteristic
                BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(temp_CharacteristicInfo.getUuid(), temp_CharacteristicInfo.getProperties(), temp_CharacteristicInfo.getPermissions());
                //看看需不需要添加descriptor
                BluetoothGattDescriptorInfo descriptorInfo = temp_CharacteristicInfo.getBluetoothGattDescriptorInfo();
                if (descriptorInfo != null) {
                    //需要就先实例化descriptor
                    BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(descriptorInfo.getUuid(), descriptorInfo.permissions);
                    //添加到characteristic里
                    characteristic.addDescriptor(descriptor);

                }
                //把characteristic添加到service
                service_temp.addCharacteristic(characteristic);
            }
            //把service添加到GattServer
            bluetoothGattServer.addService(service_temp);
        }
    }

    /**
     * 发送通知给主机
     *
     * @param data           :通知的内容
     */
    public boolean notify(byte[] data,UUID UUID_SERVER,UUID UUID_CHARWRITE) {
        if (bluetoothDevice == null){
            Toast.makeText(context,"当前没有连接设备",Toast.LENGTH_SHORT).show();
            return false;
        }
        BluetoothGattCharacteristic characteristic = getCharacteristic(UUID_SERVER,UUID_CHARWRITE);
        if (bluetoothDevice != null && characteristic != null && data != null) {
            //设置写操作的类型 WRITE_TYPE_DEFAULT的情况选  底层会自动分包 不用人为分包
            characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
            //把要设置的数据装进characteristic
            characteristic.setValue(data);
            //发送出去
            return bluetoothGattServer.notifyCharacteristicChanged(bluetoothDevice, characteristic, false);
        } else {
            return false;
        }

    }

    /**
     * 获取service下的所有Characteristic
     *
     * @param serviceUuid :service的UUID
     */
    public List<BluetoothGattCharacteristic> getCharacteristicList(UUID serviceUuid) {
        //根据UUID获取service
        BluetoothGattService service = bluetoothGattServer.getService(serviceUuid);
        //获取到了service则获取其中所有的BluetoothGattCharacteristic列表并返回出去
        if (service != null) {
            return service.getCharacteristics();
        } else {
            return null;
        }
    }

    /**
     * 获取service下的所有Characteristic
     *
     * @param serviceUuid        :service的UUID
     * @param characteristicUuid : Characteristic的UUID
     */
    public BluetoothGattCharacteristic getCharacteristic(UUID serviceUuid, UUID characteristicUuid) {
        //根据UUID获取service
        BluetoothGattService service = bluetoothGattServer.getService(serviceUuid);
        //获取到了service则根据Characteristic的UUID获取Characteristic
        if (service != null) {
            return service.getCharacteristic(characteristicUuid);
        } else {
            return null;
        }
    }



    public BlePeripheralCallback getBlePeripheralCallback() {
        return blePeripheralCallback;
    }

    public void setBlePeripheralCallback(BlePeripheralCallback blePeripheralCallback) {
        this.blePeripheralCallback = blePeripheralCallback;
    }
}

2、BlePeripheralCallback.java

public interface BlePeripheralCallback {
     void onConnectionStateChange(BluetoothDevice device, int status, int newState);
     void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic,
                                       boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes);
     void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic);
}

3、BluetoothGattCharacteristicInfo.java

public class BluetoothGattCharacteristicInfo {

    //Characteristic的UUID
    private UUID uuid;
    //Characteristic的属性
    private int properties;
    //Characteristic的权限
    private int permissions;
    //该service下的Descriptor
    private  BluetoothGattDescriptorInfo bluetoothGattDescriptorInfo;

    public BluetoothGattCharacteristicInfo(UUID uuid,int properties,int permissions,BluetoothGattDescriptorInfo bluetoothGattDescriptorInfo){
        this.uuid = uuid;
        this.properties = properties;
        this.permissions = permissions;
        this.bluetoothGattDescriptorInfo = bluetoothGattDescriptorInfo;
    }

    public UUID getUuid() {
        return uuid;
    }

    public void setUuid(UUID uuid) {
        this.uuid = uuid;
    }

    public int getProperties() {
        return properties;
    }

    public void setProperties(int properties) {
        this.properties = properties;
    }

    public int getPermissions() {
        return permissions;
    }

    public void setPermissions(int permissions) {
        this.permissions = permissions;
    }

    public BluetoothGattDescriptorInfo getBluetoothGattDescriptorInfo() {
        return bluetoothGattDescriptorInfo;
    }

    public void setBluetoothGattDescriptorInfo(BluetoothGattDescriptorInfo bluetoothGattDescriptorInfo) {
        this.bluetoothGattDescriptorInfo = bluetoothGattDescriptorInfo;
    }
}

4、BluetoothGattDescriptorInfo.java

public class BluetoothGattDescriptorInfo {

    //描述者的UUID
    private UUID uuid;
    //描述者的权限
    int permissions;

    public BluetoothGattDescriptorInfo(UUID uuid,int permissions){
        this.uuid = uuid;
        this.permissions = permissions;
    }

    public UUID getUuid() {
        return uuid;
    }

    public void setUuid(UUID uuid) {
        this.uuid = uuid;
    }

    public int getPermissions() {
        return permissions;
    }

    public void setPermissions(int permissions) {
        this.permissions = permissions;
    }
}

5、BluetoothGattServiceInfo.java

public class BluetoothGattServiceInfo {

    //Service的UUID
    private UUID uuid;
    //服务的类型 SERVICE_TYPE_PRIMARY /SERVICE_TYPE_SECONDARY
    private int serviceType;
    //该service下的characteristic
    private BluetoothGattCharacteristicInfo[] characteristicInfos;



    public BluetoothGattServiceInfo(){

    }
    public BluetoothGattServiceInfo(UUID uuid,int serviceType,BluetoothGattCharacteristicInfo[] characteristicInfos){
        this.uuid = uuid;
        this.serviceType = serviceType;
        this.characteristicInfos = characteristicInfos;

    }

    public UUID getUuid() {
        return uuid;
    }

    public void setUuid(UUID uuid) {
        this.uuid = uuid;
    }

    public int getServiceType() {
        return serviceType;
    }

    public void setServiceType(int serviceType) {
        this.serviceType = serviceType;
    }

    public BluetoothGattCharacteristicInfo[] getCharacteristicInfos() {
        return characteristicInfos;
    }

    public void setCharacteristicInfos(BluetoothGattCharacteristicInfo[] characteristicInfos) {
        this.characteristicInfos = characteristicInfos;
    }


}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android BLE(低功耗蓝牙)是一种通信协议,可用于在Android设备之间进行互传数据。使用BLE,可以实现低功耗和较短的连接时间,适合用于传输小量的数据。 在Android设备之间实现BLE互传,首先需要确保设备的蓝牙功能已开启。然后,一个设备必须担任中央(Central)角色,而另一个设备则担任外围(Peripheral)角色。 在中央设备上,我们使用BluetoothAdapter类来扫描周围的外围设备,并获取设备的蓝牙地址和名称。一旦找到外围设备,可以通过Gatt连接(Gatt连接提供了传输数据的通道)来建立与外围设备的连接。 在外围设备上,我们创建一个Gatt服务并添加特征(Characteristic),特征用于存储和传输数据。特征有一个唯一的UUID(Universally Unique Identifier),可以通过这个UUID在连接的中央设备上找到该特征。 两个设备成功建立BLE连接后,中央设备可以读取和写入外围设备上的特征。可以通过Gatt连接的回调方法获取传输的数据,并进行相应的处理或显示。 为了实现BLE互传,我们可以定义一个适当的协议,规定数据的格式和内容。例如,我们可以将数据分为消息头(如发送设备的名称和数据类型)和消息体(实际的传输数据)。发送和接收数据时,中央设备和外围设备都需要按照协议进行解析。 总的来说,通过使用Android BLE,我们可以在Android设备之间实现低功耗的数据互传。通过建立BLE连接,并定义适当的协议,我们可以轻松地在设备之间传输数据。 ### 回答2: Android BLE(蓝牙低功耗)技术可以实现设备之间的互传。在Android系统中,BLE被用于建立设备之间的无线通信连接。通过BLE,设备可以相互传输小型数据,如文本、图像等。 要实现Android BLE互传功能,首先需要明确一个设备作为提供服务(Server),另一个设备作为请求服务(Client)。Server设备需要创建一个GATT Server,它负责提供服务和特征(Services和Characteristics)。Client设备需要扫描并连接到Server设备,并读取或写入Server的特征。 互传的过程可以分为以下几个步骤: 1. Server设备创建GATT Server,并添加所需的Services和Characteristics。 2. Client设备启动扫描,并搜索附近的BLE设备。 3. Client设备找到Server设备后,进行连接。 4. Client设备获取Server设备提供的Services和Characteristics。 5. Client设备通过读取或写入Server设备的特征实现数据的传输。 需要注意的是,BLE传输的数据量较小,通常限制在20字节到512字节。如果需要传输大型文件,可以将文件分割成较小的块,并逐个块进行传输。 在Android开发中,可以使用BluetoothGatt类来实现BLE互传功能。该类提供了建立BLE连接、读取和写入特征等方法。 总之,Android BLE技术能够实现设备之间的互传功能,通过设备之间的连接和特征的读写,可以进行小型数据的传输,为用户提供方便和快捷的交互体验。 ### 回答3: Android BLE(蓝牙低功耗)是一种用于在低功耗设备之间进行通信的技术。它可以在Android设备之间实现互传数据。 Android BLE可以通过两种主要模式进行数据传输:中心模式(Central Mode)和外围模式(Peripheral Mode)。 在中心模式下,Android设备可以主动搜索附近的蓝牙设备,并连接到感兴趣的设备。一旦连接建立,设备之间就可以互传数据。 在外围模式下,Android设备作为被动设备运行,等待其他设备的连接请求。一旦连接建立,外围设备也可以向其他设备互传数据。 要实现Android BLE互传数据,首先你需要确保设备支持蓝牙低功耗技术(BLE)。然后,你需要在应用程序中使用BluetoothLeScanner类进行蓝牙设备的搜索和连接。一旦设备之间建立起连接,你可以使用Gatt(Generic Attribute Profile)来传输数据。 在发送端,你需要将要发送的数据转换为字节数组,然后使用Gatt的writeCharacteristic()方法将数据写入到Characteristic中,接收端再通过readCharacteristic()方法读取数据。 当然,为了确保连接的成功和稳定性,你还需要处理蓝牙状态变化、连接状态变化和数据传输的错误处理等。 总的来说,Android BLE可以实现两个或多个设备之间的互传数据。通过使用蓝牙低功耗技术和相应的API,你可以在Android设备之间轻松实现互传数据的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值