第一次接触Android蓝牙开发时,我也被各种专业术语搞得晕头转向。BLE和经典蓝牙到底有什么区别?为什么有些设备能直接连接,有些却需要配置UUID?这些问题困扰了我很久。经过几个项目的实战积累,我发现只要掌握核心概念,蓝牙开发并没有想象中那么难。
Android蓝牙主要分为两种模式:经典蓝牙和低功耗蓝牙(BLE)。经典蓝牙适合传输大量数据,比如音频流;而BLE则是为物联网设备设计的,功耗极低,一块纽扣电池能用好几年。我在开发智能手环项目时,就深刻体会到BLE的优势 - 设备可以持续工作数月不需要充电。
开发环境搭建很简单:
java复制// 检查蓝牙支持
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
// 设备不支持蓝牙
Toast.makeText(this, "您的设备不支持蓝牙", Toast.LENGTH_SHORT).show();
return;
}
// 请求开启蓝牙
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
HBluetooth是我用过最顺手的蓝牙开发框架之一,它封装了BLE和经典蓝牙的复杂操作,让开发者可以专注于业务逻辑。下面分享我在实际项目中的集成经验。
首先在项目根目录的build.gradle中添加JitPack仓库:
gradle复制allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
然后在app模块的build.gradle中添加依赖:
gradle复制dependencies {
implementation 'com.github.g-HJY:HBluetooth:V1.3.6'
}
初始化框架建议放在Application中:
java复制public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
HBluetooth.init(this);
}
}
这里有个坑我踩过:经典蓝牙不需要特殊配置,但BLE设备必须设置正确的UUID,否则无法通信。UUID就像设备的"身份证号",每个服务都有唯一的标识。
java复制HBluetooth.BleConfig bleConfig = new HBluetooth.BleConfig();
bleConfig.withServiceUUID("0000fe61-0000-1000-8000-00805f9b34fb")
.withWriteCharacteristicUUID("0000fe61-0000-1000-8000-00805f9b34fb")
.withNotifyCharacteristicUUID("0000fe61-0000-1000-8000-00805f9b34fb")
.setMtu(200, new BleMtuChangedCallback() {
@Override
public void onSetMTUFailure(int realMtuSize, BluetoothException bleException) {
Log.e(TAG, "MTU设置失败: "+bleException.getMessage());
}
@Override
public void onMtuChanged(int mtuSize) {
Log.i(TAG, "MTU设置成功: "+mtuSize);
}
});
HBluetooth.getInstance().setBleConfig(bleConfig);
扫描是蓝牙交互的第一步,HBluetooth提供了简洁的API:
java复制HBluetooth.getInstance()
.scan(type, new ScanCallBack() {
@Override
public void onScanStart() {
Log.i(TAG, "开始扫描");
}
@Override
public void onScanFinished(List<BluetoothDevice> devices) {
if (devices != null && !devices.isEmpty()) {
// 更新设备列表
updateDeviceList(devices);
}
}
@Override
public void onError(int errorType, String errorMsg) {
showToast("扫描出错: "+errorMsg);
}
});
连接设备时要注意处理各种状态回调,我在项目中遇到过连接超时的问题,后来通过设置合理的超时时间解决了:
java复制// 设置连接超时5秒
HBluetooth.getInstance().setConnectTimeOut(5000);
HBluetooth.getInstance()
.connect(device, new ConnectCallBack() {
@Override
public void onConnecting() {
showProgressDialog("连接中...");
}
@Override
public void onConnected(Sender sender) {
dismissProgressDialog();
// 保存sender用于后续数据发送
this.sender = sender;
}
@Override
public void onDisConnected() {
runOnUiThread(() -> {
showToast("设备已断开");
updateConnectionStatus(false);
});
}
}, new BleNotifyCallBack() {
@Override
public void onNotifySuccess() {
Log.i(TAG, "通知通道建立成功");
}
});
发送数据时要考虑MTU限制,特别是对于BLE设备。我发现超过MTU的数据需要分包发送,否则会丢失:
java复制byte[] command = {0x01, 0x02, 0x03}; // 示例命令
sender.send(command, new SendCallBack() {
@Override
public void onSending(byte[] command) {
Log.d(TAG, "命令发送中...");
}
@Override
public void onSendFailure(BluetoothException e) {
Log.e(TAG, "发送失败: "+e.getMessage());
}
});
接收数据通过设置全局回调实现,这里要注意线程切换:
java复制HBluetooth.getInstance().setReceiver(new ReceiveCallBack() {
@Override
public void onReceived(DataInputStream inputStream, byte[] data) {
runOnUiThread(() -> {
String hexStr = bytesToHexString(data);
Log.d(TAG, "收到数据: "+hexStr);
updateUIWithData(data);
});
}
});
物联网设备经常需要断线重连,HBluetooth提供了便捷的重连配置:
java复制// 最多重试3次,每次间隔4秒
HBluetooth.getInstance().openReconnect(3, 4000);
对于大数据传输,合理的分包策略很重要。我在智能家居项目中这样配置:
java复制bleConfig.splitPacketToSendWhenCmdLenBeyond(true, 30, 50);
// 参数说明:
// true - 启用分包
// 30 - 分包间隔(毫秒)
// 50 - 每包长度(字节)
蓝牙操作完成后一定要释放资源,否则会导致内存泄漏:
java复制@Override
protected void onDestroy() {
super.onDestroy();
HBluetooth.getInstance().release();
}
在开发过程中,我遇到过几个典型问题:
建议开发时备一个蓝牙调试助手,可以快速验证是代码问题还是设备问题。我常用的BLE调试助手可以从各大应用市场下载,它能直观显示服务UUID和特征值,对开发帮助很大。
蓝牙开发就像学骑自行车,开始可能会摔几次,但一旦掌握就能自由驰骋。希望我的这些实战经验能帮你少走弯路,快速构建稳定的蓝牙功能。如果在实现过程中遇到问题,不妨多看看框架源码,里面有很多实用的设计思路值得学习。