After closing bluetooth socket I'm trying to open the new one with the same way, but android tells me, the socket is closed.
This is my server thread for bluetooth conenction:
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)
}
}
}
}
}
}
This is my thread from client connection:
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()
}
}
I want to have checkbox when I'm connecting to device, or when not. But after unchecking this checkbox I cannot connect again. I'm calling "cancel()" method in ConnectBLThread, it's calling
socket?.also {
manageConnectedSocket(it)
mmServerSocket?.close()
isAwaitingForBLConnectionVal = false
if(settings.isSlaveIndoorMeasurementsEnabled) {
awaitForBLConnection()
}
}
in AcceptBLThread with mmServerSocket?.close() and then I'm trying to connect again. Starting ConnectBLThread and it's give me socket, and it's even say that it's connected but closed. How to create new socket with the same UUID after previous close? Or I shouldn't close the socket at all, cause create new will be impossible?
The reason was in closing streams befor close the socket.
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()