Android蓝牙开发全面指南
本文将深入介绍Android平台上的蓝牙开发技术,涵盖传统蓝牙(BT)和低功耗蓝牙(BLE)的开发流程及最佳实践。
1、基本概念区分
经典蓝牙(Classic BT):
适合大流量数据传输(音频、文件等)
典型协议:RFCOMM、SPP、A2DP
较高功耗
低功耗蓝牙(BLE):
专为物联网设备设计
支持广播模式和连接模式
极低功耗
2、开发前准备
2.1、添加权限
<!-- 经典蓝牙 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- BLE (Android 12+) -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 仅限Android 10以下需要 -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
2.2、运行时权限申请
private fun checkPermissions() {
val requiredPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
arrayOf(
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_SCAN
)
} else {
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION
)
}
ActivityCompat.requestPermissions(this, requiredPermissions, REQ_CODE_PERMISSIONS)
}
3、经典蓝牙开发
3.1、初始化蓝牙适配器
val bluetoothAdapter: BluetoothAdapter? by lazy {
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothManager.adapter
}
// 检查蓝牙可用性
if (bluetoothAdapter?.isEnabled != true) {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
}
3.2、设备发现
private val discoveryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when(intent.action) {
BluetoothDevice.ACTION_FOUND -> {
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
device?.let { discoveredDevices.add(it) }
}
BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
// 扫描完成处理
}
}
}
}
// 开始搜索
fun startDiscovery() {
with(bluetoothAdapter) {
this?.startDiscovery() ?: showToast("蓝牙不可用")
}
}
3.3、RFCOMM通信
服务端Socket:
val uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // SPP标准UUID
val serverSocket = bluetoothAdapter?.listenUsingRfcommWithServiceRecord("MyApp", uuid)
thread {
val socket = serverSocket?.accept() // 阻塞等待连接
socket?.let { manageConnectedSocket(it) }
} 客户端连接:
device.createRfcommSocketToServiceRecord(uuid).apply {
connect()
manageConnectedSocket(this)
}
4、BLE开发核心流程
4.1、扫描BLE设备
private val bleScanner by lazy {
bluetoothAdapter?.bluetoothLeScanner
}
private val scanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
result?.device?.let { device ->
// 处理发现的设备
}
}
}
fun startBleScan() {
val settings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build()
bleScanner?.startScan(null, settings, scanCallback)
}
4.2、GATT连接管理
private var gatt: BluetoothGatt? = null
private val gattCallback = object : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
when(newState) {
BluetoothProfile.STATE_CONNECTED -> {
gatt?.discoverServices()
}
BluetoothProfile.STATE_DISCONNECTED -> {
// 断开处理
}
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
if(status == BluetoothGatt.GATT_SUCCESS) {
// 遍历所有服务
gatt?.services?.forEach { service ->
// 获取特征值等
}
}
}
}
// 建立连接
device.connectGatt(context, false, gattCallback)
4.3、读写特征值
// 读取特征值
gatt.readCharacteristic(characteristic)
override fun onCharacteristicRead(
gatt: BluetoothGatt?,
characteristic: BluetoothGattCharacteristic?,
status: Int
) {
if(status == BluetoothGatt.GATT_SUCCESS) {
val value = characteristic?.value
// 处理数据
}
}
// 写入特征值
characteristic.value = byteArrayOf(0x01, 0x02)
gatt.writeCharacteristic(characteristic)
5、高级技巧
MTU协商:
gatt.requestMtu(512) // 最大传输单元调整
override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
super.onMtuChanged(gatt, mtu, status)
// MTU改变回调
} 分包发送大数据:
const val PACKET_SIZE = 20 // BLE默认每包20字节
fun sendLargeData(data: ByteArray) {
for(i in data.indices step PACKET_SIZE) {
val chunk = data.copyOfRange(i, minOf(i + PACKET_SIZE, data.size))
characteristic.value = chunk
gatt.writeCharacteristic(characteristic)
Thread.sleep(15) // 控制发送间隔
}
} 后台持续运行:
<service
android:name=".BluetoothLeService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="connectedDevice"/>
6、常见问题解决
133错误码处理:
private fun reconnect(device: BluetoothDevice) {
handler.postDelayed({
device.connectGatt(context, false, gattCallback)
}, 2000) // 延迟重连
} 跨版本兼容方案:
fun checkPermissionGranted(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) == PERMISSION_GRANTED
} else {
checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PERMISSION_GRANTED
}
} 多设备并发管理:
class DeviceManager {
private val connectedDevices = mutableMapOf<String, BluetoothGatt>()
fun addDevice(address: String, gatt: BluetoothGatt) {
connectedDevices[address]?.close()
connectedDevices[address] = gatt
}
}
本指南涵盖了Android蓝牙开发的核心内容,实际开发时应根据具体需求选择适当的API组合。记得在所有操作完成后及时释放资源,特别是BluetoothGatt和BluetoothSocket的连接。