Android BLE设备连接以及数据读写

一、准备

权限

<!--蓝牙权限和蓝牙设备的扫描设置权限-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
 <!--扫描蓝牙需要位置权限-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

二、扫描附近的设备

我们先判断一下有没有位置权限,如果没有,是搜不到附近的设备的。这里我们要借助Handler去实现,因为蓝牙搜索有一定的时间,不可能让手机一直处于搜索蓝牙的阶段,一般是10s。

            if (mBleHandler == null) {
                   mBleHandler = new Handler();
                }
            mSppAdapter= BluetoothAdapter.getDefaultAdapter();//ble蓝牙
            mBleHandler.postDelayed(new Runnable() {
                @Override
            public void run() {
                        //10s后扫描结束
                        mSppAdapter.stopLeScan(leScanCallback);
                        mBleHandler.removeCallbacksAndMessages(null);//handler close!!!
                    }
                }, 10000);
            mSppAdapter.startLeScan(leScanCallback);

扫描到的结果会通过leScanCallback这个接口回调。

private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    String address = device.getAddress();
                    String name = device.getName();

            });
        }
    };

这里我使用了runOnUiThread,这个类似于handler的机制,可以在其中更新UI。(向用户展示搜到的设备)

三、连接

对于连接这一块的内容,笔者建议用一个Service去维护和设备的连接。


final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
    return false;
}
device.connectGatt(this, false, mGattCallback);
 private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            连接状态改变的回调
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                //Connected to GATT server.
                //连接成功之后,我们应该去寻找服务.
                try {
                    Thread.sleep(1000);
                  mBluetoothGatt.discoverServices();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //连接成功,发送消息
                mHandler.sendEmptyMessage(STATE_CONNECTED);
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    //断连发送消息
                     mHandler.sendEmptyMessage(STATE_DISCONNECTED);
                    if (mBluetoothGatt != null) {
                        mBluetoothGatt.close();
                        mBluetoothGatt = null;
                    }
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            //发现服务后,我们就要查找读写的Characteristic
            if (status == BluetoothGatt.GATT_SUCCESS) {
                isServiceDiscover = true;
                BluetoothGattService serviceRead;
                BluetoothGattService serviceWrite;
                serviceRead = gatt.getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));
                serviceWrite = gatt.getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e4555"));

                if (serviceRead != null) {
                        mNotifyCharacteristic = serviceRead.getCharacteristic(UUID.fromString("49535343-1e4d-4bd9-ba61-23c647249616"));
                }
                if (serviceWrite != null) {
                        mWriteCharacteristic = serviceWrite.getCharacteristic(UUID.fromString("49535343-8841-43f4-a8d4-ecbe34729bb3"));
                }

                if (mNotifyCharacteristic != null) {
                    //设置可以接收通知,后面介绍
                   setCharacteristicNotification(characteristic, ture);
                }

            } else {
            //服务连接失败
            }
        }

        // 如果读取值成功之后的回调
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //收到设备notify值 (设备上报值)
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            }
        }
       //也就是readDescriptor成功后
        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {

            }
        }
        //收到设备notify值 (设备上报值),根据 characteristic.getUUID()来判断发送者
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            Timber.i("onCharacteristicChanged");

            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
          

        }

        //发送命令给设备成功之后,会回调这里
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //write成功(发送值成功)
               msgSendLoopHandler.notifyObj();
            }
        }
       //调用打开通知成功后会回调这里writeDescriptor
       //也就是writeDescriptor成功后
        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                msgSendLoopHandler.notifyObj();


            }
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
        //读取Rssi值
        }
    };
msgSendLoopHandler.notifyObj();这里先不用管,文章后面介绍。

四、读写

首先我们来说读。第一部就是打开开关,就是上面说的onDescriptorWrite这里的回调,我们要怎么做呢,看下面就知道了。

public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
                                              boolean enabled) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            return;
        }
        boolean b1 = mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
        if (UUID_BLE_SPP_NOTIFY.equals(characteristic.getUuid()) {
              BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                                UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
              descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                                sendSuccess = bluetoothLeService.mBluetoothGatt.writeDescriptor(descriptor);
        }
    }

这般设置之后,便可以在onCharacteristicChanged中收到设备上报的数据了。

下面我们来说说写数据:

byte[] tempBytes = new byte[sendSize];
mWriteCharacteristic.setValue(tempBytes);
mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);

这里要注意,确保ServiceDiscover。mWriteCharacteristic是在找到服务后的地方获取的。(上面有介绍onServicesDiscovered

中)

发布了14 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qwe749082787/article/details/88796947
今日推荐