相关文章推荐
听话的皮蛋  ·  java date取年月日 java ...·  1 年前    · 
俊逸的斑马  ·  YUV与RGB互转各种公式 ...·  1 年前    · 
寂寞的领带  ·  基本绑定 - .NET MAUI | ...·  1 年前    · 

项目地址: gitee.com/bluetooth

这个项目包含多个Android模块,其中的 test2 模块就是蓝牙Gatt功能。 此项目只是一个测试的 demo ,如果要测试 Gatt蓝牙连接 的代码可以看看。

一、蓝牙Gatt连接步骤:

当时不清楚Gatt连接的流程是什么,所以写了很多冗余代码,后面也没有抽出时间去优化。 在这里写一下核心的代码分析。(项目中的Gatt蓝牙连接代码是从网上的demo修改来的, 对蓝牙数据的处理部分是实际项目中的)。

数据处理部分:1.发送Gatt数据前字符串太长的话需要对字符串进行截取,分段发送。 2.每次得到返回的Gatt数据后需要获取其中的标志和有用信息保存起来

1.连接步骤:

  • 0.确定要连接的蓝牙设备的 Mac地址
  • 1.扫描到目标蓝牙设备,得到 BluetoothDevice mSelectedDevice 对象。
  • 2.使用 mSelectedDevice.connectGatt(context,false,mGattCallback) 进行Gatt连接。
  • 3.在 BluetoothGattCallback mGattCallback 里面获取 Gatt-Service服务 ,从服务中获取 BluetoothGattCharacteristic mVIDPIDCharacteristic Gatt特征值对象。
  • 4.发送Gatt消息的时候使用 mBluetoothGatt.writeCharacteristic()
    BluetoothGattCharacteristic RxChar...; 
    RxChar.setValue(); 
    mBluetoothGatt.writeCharacteristic(RxChar)
    
  • 5.蓝牙设备返回的Gatt消息BluetoothGattCallback mGattCallback => onCharacteristicChanged 监听的方法中获取。
  • 二.详细的Gatt核心代码逻辑

    因为MainActivityTestActivity中代码都比较多,都有一些必要的代码所以没有将两个代码放到一块。

    1.代码逻辑

  • 1.进入MainActivity页面后,首先获取定位权限,打开手机蓝牙。定义目标蓝牙设备的Mac地址
    private String MAC = "54:6C:0E:35:78:18";
    
  • 2.点击开始搜索按钮后,执行蓝牙扫描操作,注册广播监听蓝牙扫描回调。在扫描到蓝牙后判断是目标蓝牙后,携带BluetoothDevice device参数跳转到TestActivity页面。
  • 3.在TestActivity页面使用BluetoothDevice mSelectedDevice接收传过来的蓝牙对象。在onResume方法里面执行connectGatt逻辑。需要定义Gatt服务的各个Id值如:RX_SERVICE_UUID、RX_CHAR_UUID、RX_CHAR_UUID_DSC、RX_DESC_UUID、RX_DESC_UUID_DES
  • 3.1使用mBluetoothGatt = mSelectedDevice.connectGatt(mContext, false, mGattCallback)进行Gatt连接
  • 3.2在BluetoothGattCallback mGattCallback回调中获取Gatt连接信息及真正的Gatt连接操作。
  • 3.2.1在onConnectionStateChange方法判断Gatt连接状态if (status == BluetoothGatt.GATT_SUCCESS) {}
  • 3.2.2在onServicesDiscovered方法中获取Gatt-Service服务List<BluetoothGattService> services = gatt.getServices();
  • 3.3.3在使用Gatt-Service的特征值连接时需要:ServiceId:RX_SERVICE_UUID、CharaId:RX_CHAR_UUID_DSC、DescriptorId:RX_CHAR_UUID_DSC。最后取到BluetoothGattDescriptor descriptor,使用mBluetoothGatt.writeDescriptor(descriptor);进行真正的连接。
  • 3.3.4在onDescriptorWrite方法中监听连接状态,这里的连接成功才是真正的连接成功!
  • 4.点击发送消息按钮,处理数据后使用sendData(byte[] value)方法执行发送Gatt数据的逻辑,在onCharacteristicWrite回调方法中可以监听到发送的数据。onCharacteristicRead方法没有实际作用。
  • 5.在onCharacteristicChanged回调方法中获取从蓝牙设备返回的数据,对返回的数据做处理。
  • 三.其他代码分析

    如果要使用MainActivity页面的一些代码,要注意的是:

    在配置private String MAC = "54:6C:0E:35:78:18";蓝牙Mac地址后,如果扫描到目标蓝牙会直接跳到TestActivity的问题。

    主要在MainActivity中:

  • 1.获取定位权限及回调
    private void requestPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            int checkAccessFinePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
            if (checkAccessFinePermission != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_ACCESS_LOCATION);
                Log.e(getPackageName(), "没有权限,请求权限");
                return;
            Log.e(getPackageName(), "已有定位权限");
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 1: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.e(getPackageName(), "开启权限permission granted!");
                } else {
                    Log.e(getPackageName(), "没有定位权限,请先开启!");
                    Toast.makeText(this, "权限没有开启!", Toast.LENGTH_SHORT).show();
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
  • 2.打开蓝牙功能
    private boolean openBluetooth(BluetoothAdapter blueToothClient) {
        if (blueToothClient != null && !blueToothClient.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, REQUEST_OPEN_BT_CODE);
            return false;
        return true;
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_OPEN_BT_CODE) {
            Boolean success = resultCode == RESULT_OK;
            showToast(success ? "打开蓝牙成功!" : "打开蓝牙失败!");
            if (success) search(null);
            if (success) getBindDevice(null);
    
  • 3.对列表蓝牙操作弹窗DeviceActionFragment
  • 4.点击蓝牙列表中的连接蓝牙,先进行蓝牙绑定操作。
    BleHelper.bond(device);
    
  • 4.1在配对的情况下进行数据传输,这里使用蓝牙手机、蓝牙耳机测试一直有问题。
    BleHelper.connectDevice(blueToothClient, device, MainActivity.this);  
    
  • 5.如果知道目标蓝牙的Pin码的话,在上面绑定的过程中会拦截蓝牙Pin配对过程直接使用代码进行配对连接。
  • 6.蓝牙断开连接,在DeviceActionFragment中。
    Boolean remove = BleHelper.removeBonds(bluetoothDevice);
    Toast.makeText(this.getActivity(), remove ? "断开成功!" : "断开失败!", Toast.LENGTH_SHORT).show();
        跃跃2020
            Android、前端菜鸟
           
    粉丝
  •