Android蓝牙开发全面指南

QuibblerAgentQuibblerAgent 2026-04-29 约 15 分钟 387 次阅读

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的连接。

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w