Android 蓝牙工具类封装:支持经典蓝牙与 BLE,兼容高版本权限

为了优化经典蓝牙(Classic Bluetooth)和低功耗蓝牙(Bluetooth Low Energy, BLE)的操作,我们可以将功能封装到一个工具类中,支持扫描、连接、通信,并兼容高版本 Android 的动态权限申请。以下是完整的工具类实现。

  1. 工具类功能
    经典蓝牙:

扫描设备。

连接设备。

发送和接收数据。

BLE 蓝牙:

扫描设备。

连接设备。

发送和接收数据(通过 GATT 特征值)。

权限管理:

动态申请权限(包括 ACCESS_FINE_LOCATION、BLUETOOTH_SCAN、BLUETOOTH_CONNECT)。

高版本兼容:

支持 Android 12 及以上版本的权限要求。

  1. 工具类实现
    2.1 BluetoothHelper.java

    import android.Manifest;
    import android.annotation.SuppressLint;
    import android.bluetooth.*;
    import android.bluetooth.le.BluetoothLeScanner;
    import android.bluetooth.le.ScanCallback;
    import android.bluetooth.le.ScanResult;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.pm.PackageManager;
    import android.os.Build;
    import android.os.Handler;
    import android.os.Looper;
    import androidx.annotation.NonNull;
    import androidx.core.app.ActivityCompat;
    import androidx.core.content.ContextCompat;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;

    public class BluetoothHelper {

     private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // SPP UUID
     private static final int PERMISSION_REQUEST_CODE = 100;
    
     private Context context;
     private BluetoothAdapter bluetoothAdapter;
     private BluetoothLeScanner bleScanner;
     private BluetoothSocket bluetoothSocket;
     private BluetoothGatt bluetoothGatt;
     private Handler handler;
     private List<BluetoothDevice> classicDevices = new ArrayList<>();
     private List<BluetoothDevice> bleDevices = new ArrayList<>();
    
     // BLE 相关变量
     private BluetoothGattCharacteristic writeCharacteristic;
     private BluetoothGattCharacteristic notifyCharacteristic;
    
     // 回调接口
     public interface ScanCallback {
         void onClassicDeviceFound(BluetoothDevice device);
         void onBleDeviceFound(BluetoothDevice device);
         void onScanFailed(String error);
     }
    
     public interface ConnectionCallback {
         void onConnected();
         void onConnectionFailed(String error);
     }
    
     public interface DataCallback {
         void onDataReceived(byte[] data);
         void onDataSent(boolean success);
     }
    
     public BluetoothHelper(Context context) {
         this.context = context;
         this.handler = new Handler(Looper.getMainLooper());
         this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
         if (bluetoothAdapter != null) {
             this.bleScanner = bluetoothAdapter.getBluetoothLeScanner();
         }
     }
    
     // 检查权限
     public boolean checkPermissions() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
             return ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED &&
                     ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED &&
                     ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
         } else {
             return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
         }
     }
    
     // 请求权限
     public void requestPermissions() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
             ActivityCompat.requestPermissions((MainActivity) context,
                     new String[]{
                             Manifest.permission.BLUETOOTH_SCAN,
                             Manifest.permission.BLUETOOTH_CONNECT,
                             Manifest.permission.ACCESS_FINE_LOCATION
                     },
                     PERMISSION_REQUEST_CODE);
         } else {
             ActivityCompat.requestPermissions((MainActivity) context,
                     new String[]{
                             Manifest.permission.ACCESS_FINE_LOCATION
                     },
                     PERMISSION_REQUEST_CODE);
         }
     }
    
     // 开始扫描经典蓝牙设备
     public void startClassicScan(ScanCallback callback) {
         if (!checkPermissions()) {
             callback.onScanFailed("Permissions not granted");
             return;
         }
    
         classicDevices.clear();
         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
         context.registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 String action = intent.getAction();
                 if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                     BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                     classicDevices.add(device);
                     callback.onClassicDeviceFound(device);
                 }
             }
         }, filter);
    
         bluetoothAdapter.startDiscovery();
     }
    
     // 开始扫描 BLE 设备
     @SuppressLint("MissingPermission")
     public void startBleScan(ScanCallback callback) {
         if (!checkPermissions()) {
             callback.onScanFailed("Permissions not granted");
             return;
         }
    
         bleDevices.clear();
         bleScanner.startScan(new ScanCallback() {
             @Override
             public void onScanResult(int callbackType, ScanResult result) {
                 BluetoothDevice device = result.getDevice();
                 bleDevices.add(device);
                 callback.onBleDeviceFound(device);
             }
    
             @Override
             public void onScanFailed(int errorCode) {
                 callback.onScanFailed("BLE scan failed with error code: " + errorCode);
             }
         });
     }
    
     // 停止扫描
     @SuppressLint("MissingPermission")
     public void stopScan() {
         bluetoothAdapter.cancelDiscovery();
         if (bleScanner != null) {
             bleScanner.stopScan(null);
         }
     }
    
     // 连接经典蓝牙设备
     public void connectClassicDevice(BluetoothDevice device, ConnectionCallback callback) {
         new Thread(() -> {
             try {
                 bluetoothSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
                 bluetoothSocket.connect();
                 handler.post(callback::onConnected);
             } catch (IOException e) {
                 handler.post(() -> callback.onConnectionFailed(e.getMessage()));
             }
         }).start();
     }
    
     // 连接 BLE 设备
     @SuppressLint("MissingPermission")
     public void connectBleDevice(BluetoothDevice device, BluetoothGattCallback gattCallback) {
         bluetoothGatt = device.connectGatt(context, false, gattCallback);
     }
    
     // 发送数据(经典蓝牙)
     public void sendClassicData(byte[] data, DataCallback callback) {
         new Thread(() -> {
             try {
                 OutputStream outputStream = bluetoothSocket.getOutputStream();
                 outputStream.write(data);
                 handler.post(() -> callback.onDataSent(true));
             } catch (IOException e) {
                 handler.post(() -> callback.onDataSent(false));
             }
         }).start();
     }
    
     // 接收数据(经典蓝牙)
     public void receiveClassicData(DataCallback callback) {
         new Thread(() -> {
             try {
                 InputStream inputStream = bluetoothSocket.getInputStream();
                 byte[] buffer = new byte[1024];
                 int bytes;
                 while ((bytes = inputStream.read(buffer)) != -1) {
                     byte[] receivedData = new byte[bytes];
                     System.arraycopy(buffer, 0, receivedData, 0, bytes);
                     handler.post(() -> callback.onDataReceived(receivedData));
                 }
             } catch (IOException e) {
                 handler.post(() -> callback.onDataReceived(null));
             }
         }).start();
     }
    
     // 发送数据(BLE)
     @SuppressLint("MissingPermission")
     public void sendBleData(byte[] data, DataCallback callback) {
         if (writeCharacteristic != null && bluetoothGatt != null) {
             writeCharacteristic.setValue(data);
             bluetoothGatt.writeCharacteristic(writeCharacteristic);
             handler.post(() -> callback.onDataSent(true));
         } else {
             handler.post(() -> callback.onDataSent(false));
         }
     }
    
     // 启用通知以接收数据(BLE)
     @SuppressLint("MissingPermission")
     public void enableBleNotifications(BluetoothGattCharacteristic characteristic, DataCallback callback) {
         if (bluetoothGatt != null) {
             bluetoothGatt.setCharacteristicNotification(characteristic, true);
             BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                     UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
             if (descriptor != null) {
                 descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                 bluetoothGatt.writeDescriptor(descriptor);
             }
         }
     }
    
     // 断开连接
     public void disconnect() {
         try {
             if (bluetoothSocket != null) {
                 bluetoothSocket.close();
             }
             if (bluetoothGatt != null) {
                 bluetoothGatt.disconnect();
                 bluetoothGatt.close();
             }
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
    

    }

2.2 使用示例

扫描设备

BluetoothHelper bluetoothHelper = new BluetoothHelper(this);

// 扫描经典蓝牙设备
bluetoothHelper.startClassicScan(new BluetoothHelper.ScanCallback() {
    @Override
    public void onClassicDeviceFound(BluetoothDevice device) {
        Log.d("BluetoothHelper", "Classic Device Found: " + device.getName());
    }

    @Override
    public void onBleDeviceFound(BluetoothDevice device) {
        Log.d("BluetoothHelper", "BLE Device Found: " + device.getName());
    }

    @Override
    public void onScanFailed(String error) {
        Log.e("BluetoothHelper", "Scan Failed: " + error);
    }
});

// 扫描 BLE 设备
bluetoothHelper.startBleScan(new BluetoothHelper.ScanCallback() {
    @Override
    public void onClassicDeviceFound(BluetoothDevice device) {
        Log.d("BluetoothHelper", "Classic Device Found: " + device.getName());
    }

    @Override
    public void onBleDeviceFound(BluetoothDevice device) {
        Log.d("BluetoothHelper", "BLE Device Found: " + device.getName());
    }

    @Override
    public void onScanFailed(String error) {
        Log.e("BluetoothHelper", "Scan Failed: " + error);
    }
});

连接设备

// 连接经典蓝牙设备
bluetoothHelper.connectClassicDevice(device, new BluetoothHelper.ConnectionCallback() {
    @Override
    public void onConnected() {
        Log.d("BluetoothHelper", "Classic Device Connected");
    }

    @Override
    public void onConnectionFailed(String error) {
        Log.e("BluetoothHelper", "Connection Failed: " + error);
    }
});

// 连接 BLE 设备
bluetoothHelper.connectBleDevice(device, new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            Log.d("BluetoothHelper", "BLE Device Connected");
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            Log.d("BluetoothHelper", "BLE Device Disconnected");
        }
    }
});

经典蓝牙发送和接收数据

// 发送数据(经典蓝牙)
bluetoothHelper.sendClassicData("Hello Bluetooth".getBytes(), new BluetoothHelper.DataCallback() {
    @Override
    public void onDataReceived(byte[] data) {
        // 处理接收到的数据
    }

    @Override
    public void onDataSent(boolean success) {
        Log.d("BluetoothHelper", "Data Sent: " + success);
    }
});

// 接收数据(经典蓝牙)
bluetoothHelper.receiveClassicData(new BluetoothHelper.DataCallback() {
    @Override
    public void onDataReceived(byte[] data) {
        Log.d("BluetoothHelper", "Data Received: " + new String(data));
    }

    @Override
    public void onDataSent(boolean success) {
        // 无需处理
    }
});

BLE蓝牙发送和接收数据

// 连接 BLE 设备
bluetoothHelper.connectBleDevice(device, new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            gatt.discoverServices();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            BluetoothGattService service = gatt.getService(UUID.fromString("你的服务UUID"));
            if (service != null) {
                writeCharacteristic = service.getCharacteristic(UUID.fromString("写特征值UUID"));
                notifyCharacteristic = service.getCharacteristic(UUID.fromString("通知特征值UUID"));

                // 启用通知
                bluetoothHelper.enableBleNotifications(notifyCharacteristic, new BluetoothHelper.DataCallback() {
                    @Override
                    public void onDataReceived(byte[] data) {
                        Log.d("BluetoothHelper", "BLE Data Received: " + new String(data));
                    }

                    @Override
                    public void onDataSent(boolean success) {
                        // 无需处理
                    }
                });
            }
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        byte[] data = characteristic.getValue();
        Log.d("BluetoothHelper", "BLE Notification Data: " + new String(data));
    }
});

// 发送数据(BLE)
bluetoothHelper.sendBleData("Hello BLE".getBytes(), new BluetoothHelper.DataCallback() {
    @Override
    public void onDataReceived(byte[] data) {
        // 无需处理
    }

    @Override
    public void onDataSent(boolean success) {
        Log.d("BluetoothHelper", "BLE Data Sent: " + success);
    }
});

2.3 注意事项

权限管理:

在 Android 12 及以上版本,需要动态申请 BLUETOOTH_SCAN 和 BLUETOOTH_CONNECT 权限。

在 Android 11 及以下版本,需要动态申请 ACCESS_FINE_LOCATION 权限。

高版本兼容:

使用 @SuppressLint("MissingPermission") 忽略权限检查,确保在实际运行时已授予权限。

线程管理:

经典蓝牙的通信操作应在后台线程中进行,避免阻塞主线程。

通过以上工具类,你可以轻松实现经典蓝牙和 BLE 的扫描、连接和通信功能,并兼容高版本 Android 的权限要求。

相关推荐
奋斗的小鹰1 小时前
Android中使用Glide加载图片闪烁问题
android·glide
Wgllss1 小时前
金三银四,分享N年前准备的面试真经,可能适用绝大部分人
android·架构·android jetpack
CL_IN1 小时前
如何将聚水潭·奇门平台数据高效集成到MySQL
android·数据库·mysql
pengyu2 小时前
系统化掌握Flutter组件之Draggable/DragTarget
android·flutter·dart
_祝你今天愉快2 小时前
Android源码学习之开机动画
android·源码
Yang-Never3 小时前
OpenGL ES ->帧缓冲对象(Frame Buffer Object)离屏渲染获取纹理贴图
android·开发语言·kotlin·android studio·贴图
Andy.Zeng3 小时前
Android StrictMode 使用与原理深度解析
android·性能优化·kotlin·代码规范·内存泄漏·strictmode·耗时检测
Andy.Zeng3 小时前
《Android应用性能优化全解析:常见问题与解决方案》
android·性能优化
kfepiza3 小时前
android用java设置button之间的间距 笔记250311
android·java·前端