简介:本文深入探讨Android平台通过BLE(低功耗蓝牙)实现文件传输的技术原理、实现步骤及优化策略,结合代码示例与性能分析,为开发者提供从基础到进阶的完整指南。
BLE(Bluetooth Low Energy)是蓝牙4.0标准引入的低功耗无线通信技术,专为短距离、低数据量场景设计。其核心特点包括:
与传统蓝牙(BR/EDR)相比,BLE在文件传输场景中具有显著优势:
| 特性 | BLE | 传统蓝牙 |
|——————-|————————————-|—————————-|
| 功耗 | 毫瓦级 | 瓦级 |
| 连接时间 | <3ms | 100-300ms |
| 多设备支持 | 支持40个并发连接 | 通常7个 |
| 数据包大小 | 最大20字节(ATT协议) | 最大341字节 |
BLE文件传输特别适合以下场景:
Android BLE通信主要涉及以下类:
// 主要类关系图BluetoothManager → BluetoothAdapter → BluetoothDevice↓BluetoothGatt → BluetoothGattService → BluetoothGattCharacteristic
分片传输机制:
流量控制策略:
// 简单流量控制示例private static final int WINDOW_SIZE = 5;private AtomicInteger ackCount = new AtomicInteger(0);public void sendNextPacket() {if (ackCount.get() < WINDOW_SIZE && packetQueue.size() > 0) {BluetoothGattCharacteristic characteristic = ...;characteristic.setValue(packetQueue.poll());gatt.writeCharacteristic(characteristic);}}@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {if (status == BluetoothGatt.GATT_SUCCESS) {ackCount.incrementAndGet();sendNextPacket();}}
错误恢复机制:
// 1. 获取BluetoothAdapterBluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);BluetoothAdapter adapter = manager.getAdapter();// 2. 扫描设备(使用过滤条件)ScanFilter filter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(SERVICE_UUID)).build();ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();adapter.getBluetoothLeScanner().startScan(Arrays.asList(filter), settings, scanCallback);
// 1. 连接GATT服务器BluetoothGattCallback gattCallback = new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {if (newState == BluetoothProfile.STATE_CONNECTED) {gatt.discoverServices();}}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {// 获取传输服务BluetoothGattService service = gatt.getService(SERVICE_UUID);// 获取控制特征和数据特征controlChar = service.getCharacteristic(CONTROL_UUID);dataChar = service.getCharacteristic(DATA_UUID);}}};BluetoothDevice device = adapter.getRemoteDevice(deviceAddress);BluetoothGatt gatt = device.connectGatt(this, false, gattCallback);
// 1. 发送文件元数据public void sendFileMetadata(String fileName, long fileSize) {JSONObject metadata = new JSONObject();metadata.put("name", fileName);metadata.put("size", fileSize);controlChar.setValue(metadata.toString().getBytes());gatt.writeCharacteristic(controlChar);}// 2. 分片发送文件数据public void sendFileData(byte[] fileData) {int offset = 0;int packetSize = 20; // BLE ATT MTU通常20字节while (offset < fileData.length) {int remaining = fileData.length - offset;int chunkSize = Math.min(packetSize, remaining);byte[] packet = new byte[chunkSize];System.arraycopy(fileData, offset, packet, 0, chunkSize);dataChar.setValue(packet);gatt.writeCharacteristic(dataChar);offset += chunkSize;}}
// 请求更大的MTU(需双方支持)public void requestMtu(BluetoothGatt gatt) {gatt.requestMtu(512); // 最大可协商至512字节(Android 7.0+)}@Overridepublic void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {Log.d("BLE", "Negotiated MTU: " + mtu);// 根据新MTU调整分片大小}}
| MTU大小 | 有效载荷 | 理论吞吐量 | 实际测试值 |
|---|---|---|---|
| 20字节 | 17字节 | 1.36kbps | 0.9-1.1kbps |
| 128字节 | 123字节 | 9.84kbps | 7.2-8.5kbps |
| 512字节 | 507字节 | 40.56kbps | 32-36kbps |
BluetoothProfile.CONNECTION_PRIORITY_LOW_POWER
// 指数退避重连算法private void reconnectWithBackoff() {int retryCount = 0;int maxRetries = 5;long initialDelay = 1000; // 1秒Runnable reconnectTask = new Runnable() {@Overridepublic void run() {if (retryCount < maxRetries) {if (connectGatt()) { // 自定义连接方法return;}retryCount++;long delay = (long) (initialDelay * Math.pow(2, retryCount));handler.postDelayed(this, delay);} else {// 最终失败处理}}};handler.post(reconnectTask);}
实现CRC校验:
public static byte calculateCRC(byte[] data) {int crc = 0xFFFF;for (byte b : data) {crc ^= (b & 0xFF);for (int i = 0; i < 8; i++) {if ((crc & 0x0001) != 0) {crc >>= 1;crc ^= 0xA001;} else {crc >>= 1;}}}return (byte) (crc & 0xFF);}
端到端校验:
加密传输:
访问控制:
// 服务端特征权限设置BluetoothGattDescriptor configDescriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID);configDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);// 仅允许已配对设备访问BluetoothGattServerCallback serverCallback = new BluetoothGattServerCallback() {@Overridepublic void onConnectionStateChange(BluetoothDevice device, int status, int newState) {if (newState == BluetoothProfile.STATE_CONNECTED) {if (!device.getBondState() == BluetoothDevice.BOND_BONDED) {disconnectDevice(device);}}}};
防重放攻击:
// 使用JobScheduler协调多设备传输public void scheduleMultiDeviceTransfer() {JobInfo jobInfo = new JobInfo.Builder(JOB_ID, new ComponentName(this, TransferJobService.class)).setRequiredNetworkType(JobInfo.NETWORK_TYPE_BLUETOOTH).setPersisted(true).setPeriodic(15 * 60 * 1000) // 每15分钟.build();JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);scheduler.schedule(jobInfo);}
发送方维护传输状态:
public class TransferState {private String fileId;private long bytesSent;private long timestamp;// getters/setters...}
接收方实现状态查询:
public void queryTransferStatus(BluetoothGattCharacteristic characteristic) {characteristic.setValue(STATUS_REQUEST_OPCODE);gatt.writeCharacteristic(characteristic);}
调试工具:
adb shell dumpsys bluetooth_manager)开源库:
性能测试工具:
// 自定义吞吐量测试public void startThroughputTest(BluetoothGatt gatt, long durationMillis) {long startTime = System.currentTimeMillis();long bytesSent = 0;Runnable testTask = new Runnable() {@Overridepublic void run() {byte[] testData = new byte[128]; // 填充测试数据new Random().nextBytes(testData);BluetoothGattCharacteristic charac = gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_DATA_UUID);charac.setValue(testData);gatt.writeCharacteristic(charac);bytesSent += testData.length;if (System.currentTimeMillis() - startTime < durationMillis) {handler.postDelayed(this, 100); // 每100ms发送一次} else {double throughput = (bytesSent * 8.0) / (durationMillis / 1000.0);Log.d("TEST", "Throughput: " + throughput + " kbps");}}};handler.post(testTask);}
Android通过BLE实现文件传输需要综合考虑协议设计、性能优化和错误处理。当前技术方案在10米范围内可实现稳定传输,典型吞吐量在5-40kbps区间。未来发展方向包括:
开发者应根据具体场景选择合适的技术方案,在传输效率、功耗和可靠性之间取得平衡。建议从简单文件传输开始,逐步实现断点续传、多设备同步等高级功能。