You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android(Kotlin)通过UUID连接蓝牙设备报错的解决咨询

解决Android Kotlin蓝牙连接报错read failed, socket might closed or timeout, read ret: -1的方案
  • 核对UUID准确性
    这个错误最常见的原因是UUID不匹配。不要默认使用通用SPP UUID(00001101-0000-1000-8000-00805F9B34FB),必须和蓝牙设备端暴露的服务UUID完全一致。可以通过以下方式获取正确UUID:

    • 调用BluetoothDevice.getUuids()遍历已配对设备的支持UUID;
    • 用蓝牙调试工具(如nRF Connect)扫描设备服务,查看目标服务的UUID。
  • 配置并申请正确的蓝牙权限
    不同Android版本的蓝牙权限要求差异很大,务必配置齐全:

    • Android 12+:Manifest中添加BLUETOOTH_CONNECT、BLUETOOTH_SCAN权限,且在运行时动态申请;
    • Android 11及以下:Manifest中添加BLUETOOTH、BLUETOOTH_ADMIN、ACCESS_FINE_LOCATION权限,同样需要动态申请位置权限(蓝牙扫描依赖位置服务)。
      示例Manifest权限配置:
    <!-- Android 12+ 权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <!-- 旧版本兼容权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.bluetooth" android:required="true" />
    
  • 在独立线程中执行连接操作
    蓝牙连接属于耗时IO操作,绝对不能在主线程执行,否则会触发ANR或超时错误。推荐用协程在IO调度器中处理:

    CoroutineScope(Dispatchers.IO).launch {
        try {
            val socket = device.createRfcommSocketToServiceRecord(targetUuid)
            socket.connect()
            // 连接成功后的读写逻辑
        } catch (e: IOException) {
            // 错误处理:关闭socket、重试等
            e.printStackTrace()
            socket?.close()
        }
    }
    

    注意:连接失败后必须关闭当前socket,再尝试重新连接,避免资源泄漏。

  • 确认设备配对与连接状态

    • 确保目标设备已完成配对:未配对设备需先调用device.createBond()触发配对流程(需用户确认弹窗),配对完成后再尝试连接;
    • 检查设备是否处于可连接模式:部分蓝牙设备(如打印机、手环)需要手动进入配对/连接状态才能被外部设备连接。
  • 适配特殊设备的反射连接方案
    部分设备不支持标准的createRfcommSocketToServiceRecord()方法,可尝试通过反射获取RFCOMM通道连接:

    private fun createRfcommSocketViaReflection(device: BluetoothDevice): BluetoothSocket? {
        return try {
            val method = device.javaClass.getMethod("createRfcommSocket", Int::class.java)
            method.invoke(device, 1) as BluetoothSocket
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
    

    使用该方法创建socket后再调用connect()尝试连接。

  • 手动控制连接超时
    Android原生connect()方法没有超时参数,可通过协程的withTimeoutOrNull手动控制超时时间,避免无限等待:

    CoroutineScope(Dispatchers.IO).launch {
        val socket = device.createRfcommSocketToServiceRecord(targetUuid)
        val isConnected = withTimeoutOrNull(10000) { // 10秒超时
            socket.connect()
            true
        }
        if (isConnected == null) {
            socket.close()
            // 处理超时逻辑
        } else {
            // 连接成功
        }
    }
    

内容的提问来源于stack exchange,提问作者Christian Fiorenzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:21:57