近日,接到需要用到蓝牙解锁硬件设备的新需求,开发过程中呢也遇到许多硬件的坑,开发协议文档较简单,几句话就完了,第一次搞得我自己一脸懵逼,本来一两个小时就能写完并测试完成的过程用了两三天。哎!默默地回到这里疯狂输出,记录下一些不必要的坑。下面开始我的蓝牙开发吧!走了以前的老路,就是拿到蓝牙需求就叫我先根据设计好的密钥配对连接,花了点时间,然后靠广播接收回调各种信息。setPin()方法也一直不成功。但是时间实在是有点紧了,耗不住了,果断放弃老方法了,开始尝试ble 4.0的方式方法。几步就ok了;

第一部,初始化蓝牙

BluetoothAdapter mBluetoothAdapter;
private void getBlueToothAdapter() {
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBluetoothAdapter == null) {
        MyToast.showShort(this, "设备不支持蓝牙,已为您切换到网络模式");
        operationType = 2;
        rightTxt.setText("蓝牙模式");
        return;
    }
    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
        MyToast.showShort(this, "设备不支持蓝牙4.0");
        return;
    }
    openBlueTooth();
}

第二步,开启蓝牙



public static int BL_REQUESTCODE = 1;
private void openBlueTooth() {
    if (mBluetoothAdapter.isEnabled()) {
        MyToast.showShort(this, "蓝牙已打开");
        scanBlueTooth();
    } else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//这里是打开有提示是否开启蓝牙的方式
        startActivityForResult(enableBtIntent, BL_REQUESTCODE);
    }
}



//关闭蓝牙
private void closeBlueTooth() {
    mBluetoothAdapter.disable();
}

第三步,蓝牙扫描搜索

private void scanBlueTooth() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        //扫描需要一个回调。
        mBluetoothAdapter.startLeScan(scanCallBack);
    }
    //搜索后15秒关闭蓝牙扫描
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                mBluetoothAdapter.stopLeScan(scanCallBack);//停止扫描
            }
        }
    }, 15000);
}
//蓝牙扫描搜索回调
public BluetoothAdapter.LeScanCallback scanCallBack = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
        if (device.getName().equals("蓝牙的名字")) {//这里是根据蓝牙的名字筛选出想要连接的蓝牙,根据mac地址亦可以
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                //停止搜索蓝牙并连接蓝牙
                mBluetoothAdapter.stopLeScan(scanCallBack);
                connectBlueTooth(device);//连接设备
            }
        }
    }
};

第四步,连接蓝牙设备

BluetoothGattCharacteristic writeBluetoothCharacteristic;
BluetoothGatt writeBluetoothGatt;
private void connectBlueTooth(BluetoothDevice device) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        //参数1:上下文。//参数2:是否自动连接(当设备可以用时)//参数3:连接回调。
        mBluetoothAdapter.stopLeScan(scanCallBack);
        device.connectGatt(this, true, mGattCallback);
    }
}
//蓝牙连接回调
    private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                //连接成功
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                    //开始发现设备的服务
                    gatt.discoverServices();
                }
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                //连接断开
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            boolean success = false;
            //当服务发现之后回调这里
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
                    //根据服务UUID连接服务
                    BluetoothGattService service = gatt.getService(UUID.fromString("00001000-0000-1000-8000-00805f9b34fb"));
                    //根据特征UUID注册特征
                    BluetoothGattCharacteristic characteristic_write = findNotifyCharacteristic(service, UUID.fromString("00001001-0000-1000-8000-00805f9b34fb"));
                    BluetoothGattCharacteristic characteristic_notifi = findNotifyCharacteristic(service, UUID.fromString("00001002-0000-1000-8000-00805f9b34fb"));
                    if (characteristic_notifi != null) {
                        success = gatt.setCharacteristicNotification(characteristic_notifi, true);
                        if (success) {
                            characteristic_write.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
                            for (BluetoothGattDescriptor dp : characteristic_write.getDescriptors()) {
                                if (dp != null) {
                                    if ((characteristic_write.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
                                        dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                                    } else if ((characteristic_write.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
                                        dp.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                                    }
                                    gatt.writeDescriptor(dp);//这里触发发送指令的回调
                                }
                            }
                        }
                    }
                }
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            //调用读取READ通道后返回的数据回调
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
//                    Log.e("读取蓝牙数据", "" + BlueToothUtils.bytesToHexFun2(BlueToothUtils.JM3(characteristic.getValue())));
                }
            }
        }
    
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);            
            if (status == BluetoothGatt.GATT_SUCCESS) {//写入成功
               
            } else if (status == BluetoothGatt.GATT_FAILURE) {//写入失败
              
            } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) {//没权限
                
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            //蓝牙推送过来的数据
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
//                Log.e("蓝牙推送过来的数据", "" + BlueToothUtils.bytesToHexFun2(BlueToothUtils.JM3(characteristic.getValue())));
            }
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            writeBluetoothGatt = gatt;
            BluetoothGattService writeService = null;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
                writeService = gatt.getService(UUID.fromString("00001000-0000-1000-8000-00805f9b34fb"));
                if (writeService == null) {
                    return;
                }
                writeBluetoothCharacteristic = writeService.getCharacteristic(UUID.fromString("00001001-0000-1000-8000-00805f9b34fb"));
                if (writeBluetoothCharacteristic == null) {
                    return;
                }
                bluetooth_sendMessage(pwd, false);
            }
        }
    };
private BluetoothGattCharacteristic findNotifyCharacteristic(BluetoothGattService service, UUID characteristicUUID) {//此方法是在没有收到蓝牙的通知回调加的,最后才确定了是硬件那边本来就没给我回调信息,当然加入此方法也不会有问题
    BluetoothGattCharacteristic characteristic = null;
    List<BluetoothGattCharacteristic> characteristics = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
        characteristics = service.getCharacteristics();
        for (BluetoothGattCharacteristic c : characteristics) {
            if ((c.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0
                    && characteristicUUID.equals(c.getUuid())) {
                characteristic = c;
                break;
            }
        }
        if (characteristic != null)
            return characteristic;
        for (BluetoothGattCharacteristic c : characteristics) {
            if ((c.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0
                    && characteristicUUID.equals(c.getUuid())) {
                characteristic = c;
                break;
            }
        }
    }
    return characteristic;
}

//蓝牙发送指令
private void bluetooth_sendMessage(byte[] message, boolean flag) {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
        if (writeBluetoothCharacteristic == null) {
            return;
        }
        if (flag) {
            message = BlueToothUtils.Agreement_Encryption(message, message.length);
        }
        writeBluetoothCharacteristic.setValue(message);
        //上面的buffer数组中装的就是指令,多长? 每一位上面的数字代表什么意思在协议中查看!
        writeBluetoothGatt.writeCharacteristic(writeBluetoothCharacteristic);//向设备写入指令。
    }
}

最后加上权限。这里需要自己去动态申请6.0的定位权限

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>