无法再次打开新的蓝牙插座

Cannot open new bluetooth socket again

关闭蓝牙套接字后,我试图用同样的方式打开新的,但 android 告诉我,套接字已关闭。

这是我的蓝牙连接服务器线程:

private inner class AcceptBLThread : Thread() {
    private val mmServerSocket: BluetoothServerSocket? by lazy {
        bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(
            connectionBLName,
            UUID.fromString(connectionUUID)
        )
    }

    override fun run() {
        // Keep listening until exception occurs or a socket is returned.
        isAwaitingForBLConnectionVal = true
        Log.i(tag, "Awaiting for BL connection")
        while (isAwaitingForBLConnectionVal) {
            val socket: BluetoothSocket? = try {
                mmServerSocket?.accept()
            } catch (e: IOException) {
                Log.e(tag, "Socket's accept() method failed", e)
                isAwaitingForBLConnectionVal = false
                null
            }
            socket?.also {
                manageConnectedSocket(it)
                mmServerSocket?.close()
                isAwaitingForBLConnectionVal = false

                if(settings.isSlaveIndoorMeasurementsEnabled) {
                    awaitForBLConnection()
                }
            }
        }
    }

    // Closes the connect socket and causes the thread to finish.
    fun cancel() {
        try {
            mmServerSocket?.close()
            isBLMasterConnectedVal = false

            if(settings.isSlaveIndoorMeasurementsEnabled) {
                awaitForBLConnection()
            }

            Log.i(tag, "Master device disconnected")
            Log.i(tag, "Closed server socket")
        } catch (e: IOException) {
            Log.e(tag, "Could not close the connect socket", e)
        }
    }

    @Suppress("MoveVariableDeclarationIntoWhen")
    private fun manageConnectedSocket(socket: BluetoothSocket) {
                isBLMasterConnectedVal = true
    
                val inStream = socket.inputStream
                val outStream = socket.outputStream
                val buffer = ByteArray(1024)
                var numBytes: Int
    
                if(socket.isConnected) {
                    Log.i(tag, "Master device connected")
                } else {
                    Log.i(tag, "Master device connect failure")
                }
    
                // Keep listening to the InputStream until an exception occurs.
                while (true) {
                    // Read from the InputStream.
                    numBytes = try {
                        inStream.read(buffer)
                    } catch (e: IOException) {
                        Log.d(tag, "Input stream was disconnected", e)
                        break
                    }
                    if(numBytes == 1) {
                        val commandType = BluetoothCommands.from(buffer.toInt())
                        when(commandType) {
                            BluetoothCommands.START_INDOOR -> {
    
                            }
                            BluetoothCommands.STOP_INDOOR -> {
    
                            }
                            BluetoothCommands.SEND_DATA_TO_MASTER -> {
    
                            }
                            BluetoothCommands.ON_MASTER_DISCONNECTED -> {
                                Log.i(tag, "Master disconnected BL event")
                                Handler(Looper.getMainLooper()).postDelayed({
                                    if(settings.isSlaveIndoorMeasurementsEnabled
                                        && !isAwaitingForBLConnectionVal) {
                                        awaitForBLConnection()
                                    }
                                }, 1000)
                            }
                        }
                    }
                }
            }
        }

这是我来自客户端连接的线程:

private inner class ConnectBLThread(
        val device: BluetoothDevice,
        val connectionCallback: BLCallback?
    ) : Thread() {
        private val socket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) {
            device.createRfcommSocketToServiceRecord(UUID.fromString(connectionUUID))
        }

        override fun run() {
            bluetoothAdapter.cancelDiscovery()

            socket?.let { socket ->
                try {
                    Log.i(tag, "Connecting to slave device")
                    // Connect to the remote device through the socket. This call blocks
                    // until it succeeds or throws an exception.
                    socket.connect()
                    // The connection attempt succeeded. Perform work associated with
                    // the connection in a separate thread.
                    manageConnectedSocket(socket)
                } catch (exc: Exception) {
                    Log.i(tag, "Connecting to slave device failed")
                    connectionCallback?.onConnectionError(device.address)
                }
            }
        }

        // Closes the client socket and causes the thread to finish.
        fun cancel() {
            try {
                socket?.outputStream?.write(
                    BluetoothCommands.ON_MASTER_DISCONNECTED.value.toByteArray()
                )
                Handler(Looper.getMainLooper()).postDelayed({
                    socket?.close()
                    connectionCallback?.onDisconnected(device.address)
                },500)
            } catch (e: IOException) {
                Log.e(tag, "Could not close the client socket", e)
            }
        }

        private fun manageConnectedSocket(socket: BluetoothSocket) {
            Log.i(tag, "Connected to slave device successfully")
            slaveSockets[device.address] = socket
            connectionCallback?.onConnectedSuccessfully()
        }
    }

我希望在连接到设备时或不连接时有复选框。但是取消选中此复选框后,我无法再次连接。我在 ConnectBLThread 中调用“cancel()”方法,它调用

socket?.also {
    manageConnectedSocket(it)
    mmServerSocket?.close()
    isAwaitingForBLConnectionVal = false

    if(settings.isSlaveIndoorMeasurementsEnabled) {
        awaitForBLConnection()
    }
}

在带有 mmServerSocket?.close() 的 AcceptBLThread 中,然后我尝试再次连接。启动 ConnectBLThread,它给我套接字,它甚至说它已连接但已关闭。 如何在上次关闭后创建具有相同 UUID 的新套接字?或者我根本不应该关闭套接字,因为创建新套接字是不可能的?

原因是在关闭套接字之前关闭流。

socket.inputStream.close()
socket.outputStream.close()
Thread.sleep(1000) //it's imprortant too. You should give a time to close streams before close the socket
socket.close()