在万物互联的时代,蓝牙技术凭借其低功耗、短距离通信等优势,广泛应用于各类智能设备中,尤其是蓝牙低功耗(BLE)技术,更是成为智能穿戴、智能家居、医疗健康等领域的主流通信方式。对于 Android 开发者而言,掌握蓝牙 BLE 设备配对与数据透传的实现方法,是开发相关应用的关键技能。本文将深入探讨这一主题,为开发者提供全面的指导。
蓝牙低功耗(BLE)是蓝牙 4.0 版本引入的一项重要技术,与传统蓝牙(Classic Bluetooth)相比,BLE 具有显著的低功耗特性,能够在保证通信质量的前提下,大幅降低设备的能耗,延长电池使用寿命。这使得 BLE 非常适合应用于对功耗要求严格的设备,如智能手环、心率监测仪等。同时,BLE 还具备快速连接、短数据包传输等特点,能够满足实时性要求较高的应用场景。
在 Android 应用中开发蓝牙 BLE 功能,首先需要在 AndroidManifest.xml 文件中申请必要的权限。主要涉及两个权限:
xml<uses-permission android:name="android.permission.BLUETOOTH"/><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/><!-- 对于 Android 6.0 及以上系统,还需要动态申请位置权限,因为蓝牙扫描需要获取设备位置信息 --><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
通过 BluetoothManager 获取 BluetoothAdapter 对象,这是进行蓝牙操作的基础。示例代码如下:
javaBluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();if (bluetoothAdapter == null ||!bluetoothAdapter.isEnabled()) { // 提示用户开启蓝牙 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}使用 BluetoothAdapter 的 startLeScan() 或 BluetoothLeScanner 的 startScan() 方法进行 BLE 设备扫描。推荐使用 BluetoothLeScanner,因为它提供了更多的扫描过滤选项和更好的性能。示例代码如下:
javaBluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();ScanSettings scanSettings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build();List<ScanFilter> scanFilters = new ArrayList<>();// 可以添加扫描过滤条件,如设备名称、服务 UUID 等// scanFilters.add(new ScanFilter.Builder().setDeviceName("设备名称").build());bluetoothLeScanner.startScan(scanFilters, scanSettings, scanCallback);其中,scanCallback 是 ScanCallback 对象,用于处理扫描结果:
javaprivate ScanCallback scanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); BluetoothDevice device = result.getDevice(); // 处理扫描到的设备 } @Override public void onBatchScanResults(List<ScanResult> results) { super.onBatchScanResults(results); // 处理批量扫描结果 } @Override public void onScanFailed(int errorCode) { super.onScanFailed(errorCode); // 处理扫描失败情况 }};当扫描到目标设备后,可以通过 createBond() 方法发起配对请求:
javaBluetoothDevice device =...; // 获取到的目标设备if (device.getBondState() == BluetoothDevice.BOND_NONE) { try { Method createBondMethod = BluetoothDevice.class.getMethod("createBond"); createBondMethod.invoke(device); } catch (Exception e) { e.printStackTrace(); }}配对过程中,系统会弹出配对确认对话框,用户确认后即可完成配对。配对成功后,设备的 BondState 会变为 BluetoothDevice.BOND_BONDED。
配对成功后,需要建立与设备的连接。使用 BluetoothGatt 类来实现连接和数据通信:
javaBluetoothDevice device =...; // 已配对的设备BluetoothGatt bluetoothGatt = device.connectGatt(this, false, gattCallback);
其中,gattCallback 是 BluetoothGattCallback 对象,用于处理连接状态变化、服务发现、数据读写等事件:
javaprivate BluetoothGattCallback gattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); if (newState == BluetoothProfile.STATE_CONNECTED) { // 连接成功,开始发现服务 gatt.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // 连接断开 } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); if (status == BluetoothGatt.GATT_SUCCESS) { // 服务发现成功,获取服务和特征 List<BluetoothGattService> services = gatt.getServices(); for (BluetoothGattService service : services) { List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics(); for (BluetoothGattCharacteristic characteristic : characteristics) { // 处理特征 } } } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicRead(gatt, characteristic, status); if (status == BluetoothGatt.GATT_SUCCESS) { // 读取特征值成功 byte[] value = characteristic.getValue(); // 处理读取到的数据 } } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); if (status == BluetoothGatt.GATT_SUCCESS) { // 写入特征值成功 } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); // 特征值发生变化,处理通知数据 byte[] value = characteristic.getValue(); // 处理接收到的数据 }};读取数据:找到需要读取的特征后,调用 readCharacteristic() 方法读取数据:
javaBluetoothGattCharacteristic characteristic =...; // 获取到的需要读取的特征boolean result = bluetoothGatt.readCharacteristic(characteristic);
写入数据:将数据写入特征时,需要先设置特征的写入权限,然后调用 writeCharacteristic() 方法:
javaBluetoothGattCharacteristic characteristic =...; // 获取到的需要写入的特征characteristic.setValue(data); // data 为要写入的数据characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);boolean result = bluetoothGatt.writeCharacteristic(characteristic);
如果需要接收设备发送的实时数据,可以开启特征的通知功能:
javaBluetoothGattCharacteristic characteristic =...; // 获取到的需要开启通知的特征BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));characteristic.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);boolean result = bluetoothGatt.writeDescriptor(descriptor);连接失败可能是由于设备未开启、距离过远、设备忙等原因导致。解决方法包括检查设备状态、缩短连接距离、等待设备空闲后重试等。
数据读写失败可能是由于特征权限不足、设备未就绪等原因引起。需要确保特征具有相应的读写权限,并在设备就绪后进行读写操作。