Android Studio中Kotlin连接蓝牙设备失败,UUID是否为问题根源?
解决蓝牙连接的RuntimeException问题及UUID获取方案
一、先修复两个明显的错误
1. 替换错误的UUID
你当前使用的00000000-0000-1000-8000-00805F9B34FB是无效的占位UUID,绝大多数蓝牙串口设备采用SPP(串口协议)标准UUID,替换成以下值:
val my_uuidpar = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
2. 正确启动连接线程
你现在调用connectedDevice?.run()只是在UI线程同步执行代码,会阻塞主线程引发ANR或异常,必须调用start()开启独立线程:
connectedDevice?.start()
二、排查真实异常原因
InvocationTargetException只是底层错误的包装类,你需要打印异常的cause才能找到真正问题,修改ConnectThread的run方法:
@SuppressLint("MissingPermission") public override fun run() { bluetoothAdapter?.cancelDiscovery() mmSocket?.let { socket -> try { socket.connect() // manageMyConnectedSocket(socket) } catch (e: Exception) { // 打印真实异常根源 Log.e("BluetoothConnect", "连接失败", e.cause ?: e) cancel() } } }
常见真实原因包括:权限未授予、设备不支持目标UUID、设备已断开、连接超时等。
三、获取设备正确UUID的方法
如果替换SPP UUID后仍无法连接,可通过以下方式获取设备真实服务UUID:
1. 通过SDP扫描获取UUID
调用fetchUuidsWithSdp()触发服务发现,通过广播接收结果:
// 1. 注册广播接收器(记得在onDestroy时注销) private val uuidReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (BluetoothDevice.ACTION_UUID == intent?.action) { val uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID) uuids?.forEach { uuid -> val targetUuid = (uuid as ParcelableUuid).uuid Log.d("DeviceUUID", "扫描到UUID: $targetUuid") // 可直接用此UUID尝试连接 } } } } // 2. 点击设备时启动SDP扫描 scannedDevices.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> val device = devicemap[position] ?: return@OnItemClickListener registerReceiver(uuidReceiver, IntentFilter(BluetoothDevice.ACTION_UUID)) device.fetchUuidsWithSdp() }
2. 查询设备手册或厂商文档
如果是自定义蓝牙设备,厂商通常会在产品文档中提供服务UUID,这是最可靠的方式。
3. 反射获取RFCOMM通道(备用方案)
当SDP扫描失败时,可尝试通过反射直接指定RFCOMM通道创建socket:
private fun createRfcommSocket(device: BluetoothDevice, channel: Int = 1): BluetoothSocket? { return try { val method = device.javaClass.getMethod("createRfcommSocket", Int::class.java) method.invoke(device, channel) as BluetoothSocket } catch (e: Exception) { Log.e("Bluetooth", "反射创建socket失败", e) null } }
使用时替换原有的createRfcommSocketToServiceRecord调用即可,通道通常从1开始尝试。
四、Android 12+权限检查
确保已动态申请并获得BLUETOOTH_CONNECT和BLUETOOTH_SCAN权限:
val permissions = arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT) if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, permissions, 1001) }
内容的提问来源于stack exchange,提问作者stair case to heaven
相关产品推荐
相关产品推荐

