Android低功耗蓝牙(BLE)使用详解

逃离我推掉我的手 2022-05-12 09:58 375阅读 0赞

代码地址如下:
http://www.demodashi.com/demo/13390.html

与普通蓝牙相比,低功耗蓝牙显著降低了能量消耗,允许Android应用程序与具有更严格电源要求的BLE设备进行通信,如接近传感器、心率传感器等低功耗设备。

声明蓝牙权限

  和使用普通蓝牙一样,在使用低功耗蓝牙时也需要在AndroidManifest声明蓝牙权限,声明蓝牙权限的代码如下

  1. <uses-permission android:name="android.permission.BLUETOOTH"/>
  2. <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

如果想让你的App只适用于BLE设备,可以在AndroidManifest中继续添加以下代码

  1. <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

如果想让你的App适用于不支持BLE的设备,只需要将required="true"改为required="false"然后在代码中通过以下方法来判断设备是否支持BLE,

  1. private void checkIsSupportBLE() {
  2. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
  3. Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
  4. finish();
  5. }
  6. }

注:

LE信标往往与位置有关,如果想要通过`BluetoothLeScanner 方法来获取正确的扫描结果,需要在AndroidManifest中声明位置权限,声明位置权限可以使用ACCESS_COARSE_LOCATION或则 ACCESS_FINE_LOCATION ,如过不声明位置权限,将不会返回蓝牙的扫描结果。

开启BLE

  开启BLE只需要以下两步

  1. 拿到BluetoothAdapter。

    在Android系统中只有一个BluetoothAdapter,可以通过以下方法来获取

    1. private void obtainBluetoothAdapter() {
    2. final BluetoothManager bluetoothManager =
    3. (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    4. mBluetoothAdapter = bluetoothManager.getAdapter();
    5. }
  2. 开启蓝牙。

    通过isEnabled()可以判断是否已经开启BLE,如果没有开启则可以通过以下方法来开启

    //注册广播接受者
    private void initReceiver() {

    1. IntentFilter filter = new IntentFilter();
    2. filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    3. registerReceiver(mReceiver, filter);
    4. }

    //新建监听蓝牙状态变化的广播
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {

    1. @Override
    2. public void onReceive(Context context, Intent intent) {
    3. final String action = intent.getAction();
    4. if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
    5. final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
    6. BluetoothAdapter.ERROR);
    7. switch (state) {
    8. case BluetoothAdapter.STATE_OFF:
    9. mBluetoothState.setText("Bluetooth off");
    10. break;
    11. case BluetoothAdapter.STATE_TURNING_OFF:
    12. mBluetoothState.setText("Turning Bluetooth off...");
    13. break;
    14. case BluetoothAdapter.STATE_ON:
    15. mBluetoothState.setText("Bluetooth on");
    16. break;
    17. case BluetoothAdapter.STATE_TURNING_ON:
    18. mBluetoothState.setText("Turning Bluetooth on...");
    19. break;
    20. }
    21. }
    22. }
    23. };

此广播包含额外字段 EXTRA_STATEEXTRA_PREVIOUS_STATE,二者分别包含新的和旧的蓝牙状态。 这些额外字段可能的值包括 STATE_TURNING_ONSTATE_ONSTATE_TURNING_OFFSTATE_OFF。侦听此广播适用于检测在您的应用运行期间对蓝牙状态所做的更改。

扫描BLE设备

  扫描蓝牙设备可以通过 startLeScan(BluetoothAdapter.LeScanCallback)startLeScan(UUID[], BluetoothAdapter.LeScanCallback)方法,这两种扫描BLE设备的区别如下。

  • startLeScan(BluetoothAdapter.LeScanCallback)方法扫描的是周围所有的BLE设备。
  • startLeScan(UUID[], BluetoothAdapter.LeScanCallback)只扫描和UUID相匹配的设备。

可以发现无论通过哪种方式扫描蓝牙都必须要实现LeScanCallback回调方法,此方法是用来获取蓝牙扫描结果。

  通过以上两种方式实现扫描BLE设备的代码如下:

  1. 通过startLeScan(BluetoothAdapter.LeScanCallback)方法扫描蓝牙的代码如下

    1. //扫描BLE设备
    2. private void scanLeDevice(final boolean enable) {
    3. if (enable) {
    4. // Stops scanning after a pre-defined scan period.
    5. mHandler.postDelayed(new Runnable() {
    6. @Override
    7. public void run() {
    8. mScanning = false;
    9. mBluetoothAdapter.stopLeScan(mLeScanCallback);
    10. }
    11. }, SCAN_PERIOD);
    12. mScanning = true;
    13. mBluetoothAdapter.startLeScan(mLeScanCallback);
    14. } else {
    15. mScanning = false;
    16. mBluetoothAdapter.stopLeScan(mLeScanCallback);
    17. }
    18. }
    19. //扫描结果回调
    20. private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
    21. @Override
    22. public void onLeScan(final BluetoothDevice device, int rssi,
    23. byte[] scanRecord) {
    24. runOnUiThread(new Runnable() {
    25. @Override
    26. public void run() {
    27. mLeDeviceListAdapter.addDevice(device);
    28. mLeDeviceListAdapter.notifyDataSetChanged();
    29. }
    30. });
    31. }
    32. };
  2. 通过startLeScan(UUID[], BluetoothAdapter.LeScanCallback)方法扫描蓝牙的代码如下

    1. private void scanLeDeviceByUUID() {
    2. mBluetoothAdapter.startLeScan(new UUID[]{RX_SERVICE_UUID}, mLeScanCallback);
    3. }

    再次声明:

    LE信标往往与位置有关,如果想要通过BluetoothLeScanner 方法来获取正确的扫描结果,需要在AndroidManifest中声明位置权限,声明位置权限可以使用ACCESS_COARSE_LOCATION或则 ACCESS_FINE_LOCATION ,如过不声明位置权限,将不会返回蓝牙的扫描结果。

连接BLE设备

   要进行BLE设备之间的通讯,首先应该进行设备之间的连接,可以通过device.connectGatt (Context context,boolean autoConnect, BluetoothGattCallback callback)方法来连接设备。

  • autoConnect是设置当BLE设备可用时是否自动进行连接。
  • device就是通过扫描BLE设备获得的。
  • callback则是连接指定设备后的回掉,可以在回掉中知道是否建立连接、连接断开、以及获取设备之间传输的数据。

    以下是BluetoothGattCallback类中具体的方法163b0e9d09b9cb2d_w_663_h_308_f_png_s_87783

下面我会介绍几个比较常用的方法:

  • onConnectionStateChange此方法的作用是可以获得设备连接的状态,如“成功连接”、“断开连接”。
  • onServicesDiscovered当远程设备的服务,特性和描述符列表已更新时(即发现新服务),调用此方法。
  • onCharacteristicChanged远程特征变化会调用此方法,即BLE设备的状态发生了变化会调用此方法。

onCharacteristicChanged方法就是相当于BLE设备对你操作的回应,如打开BLE设备成功等,然后在此方法回掉之后,便可以继续下一步操作了。

操作BLE设备

  在设备连接之后,就可以向BLE设备发送命令来操作BLE设备了,向BLE写数据的代码如下

  1. public boolean writeByteToBleDevice(byte[] data) {
  2. BluetoothGattService mBluetoothGattService = mBluetoothGatt.getService(RX_SERVICE_UUID);
  3. if (mBluetoothGattService == null) {
  4. return false;
  5. }
  6. BluetoothGattCharacteristic characteristic = mBluetoothGattService.getCharacteristic(RX_SERVICE_UUID);
  7. if (characteristic == null) {
  8. return false;
  9. }
  10. boolean b = characteristic.setValue(data);
  11. return b && mBluetoothGatt.writeCharacteristic(characteristic);
  12. }

在向BLE设备发送数据之后,就可以在onCharacteristicChanged方法中获得BLE设备的状态了。

项目结构

项目代码结构图截图

cRXoL2PBdLwzeK5xDEX.jpg

结束语

  这篇文章拖了这么久,总算写完了,本来打算在上一篇蓝牙文章写完后就写这篇,结果中间公司忙着上线新的项目,加班加点将近一个月,就没时间写这篇文章了,在项目上线之后就立马开始写这篇文章,希望这篇文章能帮到想要学习蓝牙的朋友。

Android低功耗蓝牙(BLE)使用详解

代码地址如下:
http://www.demodashi.com/demo/13390.html

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

发表评论

表情:
评论列表 (有 0 条评论,375人围观)

还没有评论,来说两句吧...

相关阅读