概述
Kable(com.juul.kable:core)是一个专为Android蓝牙低功耗(BLE)开发设计的Kotlin协程友好库。它通过提供简洁的API和响应式编程模式,极大地简化了BLE设备交互的复杂性。本文将详细介绍Kable的使用方法,并重点讨论其在Android高版本系统中的兼容性问题。
环境配置
添加依赖
在项目的build.gradle.kts文件中添加Kable依赖:
kotlin
dependencies {
implementation("com.juul.kable:core:0.33.0")
}
权限声明
在AndroidManifest.xml中声明必要的BLE权限:
xml
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30" />
<!-- Android 12+ 额外权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<!-- 可选:声明BLE功能 -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
核心功能使用
设备扫描
Kable提供了简洁的API来扫描附近的BLE设备:
kotlin
import com.juul.kable.Scanner
import com.juul.kable.Filter
import kotlinx.coroutines.flow.collect
class DeviceScanner {
suspend fun scanForDevices(deviceNamePrefix: String) {
val scanner = Scanner {
filters = listOf(Filter.NamePrefix(deviceNamePrefix))
}
scanner.advertisements.collect { advertisement ->
println("发现设备: ${advertisement.name ?: "未知"}, RSSI: ${advertisement.rssi}")
// 处理找到的设备
}
}
}
设备连接与通信
建立与BLE设备的连接并进行数据交互:
kotlin
import com.juul.kable.Peripheral
import com.juul.kable.Characteristic
class BleDeviceManager {
private var peripheral: Peripheral? = null
suspend fun connectToDevice(advertisement: Advertisement) {
peripheral = Peripheral(advertisement)
try {
// 建立连接
peripheral?.connect()
// 发现服务
discoverServices()
} catch (e: Exception) {
println("连接失败: ${e.message}")
disconnect()
}
}
private suspend fun discoverServices() {
val services = peripheral?.services()
services?.forEach { service ->
println("发现服务: ${service.uuid}")
service.characteristics.forEach { characteristic ->
println("特征值: ${characteristic.uuid}")
// 根据需求进行读写操作
}
}
}
suspend fun readCharacteristic(characteristic: Characteristic): ByteArray? {
return peripheral?.read(characteristic)
}
suspend fun writeCharacteristic(characteristic: Characteristic, data: ByteArray) {
peripheral?.write(characteristic, data)
}
suspend fun enableNotifications(characteristic: Characteristic) {
peripheral?.observe(characteristic)?.collect { data ->
// 处理接收到的数据
println("收到数据: ${data.toHexString()}")
}
}
fun disconnect() {
peripheral?.disconnect()
peripheral = null
}
}
Android高版本兼容性指南
权限处理策略
针对Android 12及更高版本,需要采用新的权限请求策略:
kotlin
class BlePermissionHelper(
private val activity: FragmentActivity
) {
private val permissionLauncher = activity.registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
if (permissions.all { it.value }) {
onPermissionsGranted()
} else {
onPermissionsDenied()
}
}
fun checkAndRequestPermissions() {
val requiredPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT
)
} else {
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION
)
}
permissionLauncher.launch(requiredPermissions)
}
private fun onPermissionsGranted() {
// 权限已授予,开始BLE操作
}
private fun onPermissionsDenied() {
// 处理权限被拒绝的情况
}
}
Android 12+ 特定配置
kotlin
fun createAndroid12CompatibleScanner(context: Context): Scanner {
return Scanner {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
android {
callerPackageName = context.packageName
isLegacy = false
// 其他Android 12特定配置
}
}
}
}
最佳实践建议
- 生命周期管理
kotlin
class LifecycleAwareBleManager(
lifecycle: Lifecycle,
private val context: Context
) : DefaultLifecycleObserver {
init {
lifecycle.addObserver(this)
}
override fun onStart(owner: LifecycleOwner) {
if (checkPermissions()) {
startBleOperations()
}
}
override fun onStop(owner: LifecycleOwner) {
stopBleOperations()
}
private fun checkPermissions(): Boolean {
// 权限检查逻辑
return true
}
private fun startBleOperations() {
// 启动BLE相关操作
}
private fun stopBleOperations() {
// 停止BLE相关操作
}
}
- 错误处理与重连机制
kotlin
class RobustBleConnection {
private var connectionAttempts = 0
private val maxAttempts = 3
suspend fun connectWithRetry(peripheral: Peripheral) {
while (connectionAttempts < maxAttempts) {
try {
peripheral.connect()
connectionAttempts = 0
return
} catch (e: Exception) {
connectionAttempts++
delay(2000) // 等待2秒后重试
}
}
throw Exception("连接失败,已达最大重试次数")
}
}
- 资源清理
kotlin
class SafeBleOperator : AutoCloseable {
private val peripherals = mutableListOf<Peripheral>()
suspend fun addPeripheral(advertisement: Advertisement) {
val peripheral = Peripheral(advertisement)
peripheral.connect()
peripherals.add(peripheral)
}
override fun close() {
peripherals.forEach { it.disconnect() }
peripherals.clear()
}
}
// 使用示例
fun exampleUsage() {
SafeBleOperator().use { operator ->
// 执行BLE操作
}
// 自动调用close()方法清理资源
}
常见问题与解决方案
- 权限被拒绝处理
kotlin
fun handlePermissionDenied(context: Context) {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", context.packageName, null)
}
context.startActivity(intent)
}
- 蓝牙适配器检查
kotlin
fun checkBluetoothAvailability(context: Context): Boolean {
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val bluetoothAdapter = bluetoothManager.adapter
return bluetoothAdapter != null && bluetoothAdapter.isEnabled
}
总结
Kable库为Android BLE开发提供了现代化、协程友好的解决方案。通过本文的介绍,您应该能够:
- 理解Kable的基本用法和核心功能
- 掌握在Android高版本中处理BLE权限的正确方法
- 实现健壮的BLE连接和通信机制
- 遵循最佳实践来管理BLE资源
随着Android系统的不断更新,建议开发者始终使用Kable的最新版本,并密切关注Android官方文档中关于BLE权限和API的变更,以确保应用的长期兼容性和稳定性。
Kable的简洁API和强大的功能使其成为Android BLE开发的首选库之一,特别是在需要支持高版本Android系统的项目中。