private val activity = activity init { val btAdapter = BluetoothAdapter.
getDefaultAdapter() if (btAdapter != null) { this.
serverSocket = btAdapter.
listenUsingRfcommWithServiceRecord("test", uuid) // 1 this.
cancelled = false } else { this.
serverSocket = null this.
cancelled = true } } override fun run() { var socket: BluetoothSocket while(true) { if (this.
cancelled) { break } try { socket = serverSocket!!.
accept() // 2 } catch(e: IOException) { break } if (!this.
cancelled && socket != null) { Log.
i("server", "Connecting") BluetoothServer(this.
activity, socket).
start() // 3 } } } fun cancel() { this.
cancelled = true this.
serverSocket!!.
close() }}There are three key things in the above code that enable the server (marked with the numbered comments):Create a server socket, identified by the uuid, in the class constructorOnce thread execution started wait for the client connections using accept() methodOnce client established connection accept() method returns a BluetoothSocket reference that gives access to the input and output streams.
We use this socket to start the Server thread.
The BluetoothServer class looks like the following:class BluetoothServer(private val activity: MainActivity, private val socket: BluetoothSocket): Thread() { private val inputStream = this.
socket.
inputStream private val outputStream = this.
socket.
outputStream override fun run() { try { val available = inputStream.
available() val bytes = ByteArray(available) Log.
i("server", "Reading") inputStream.
read(bytes, 0, available) val text = String(bytes) Log.
i("server", "Message received") Log.
i("server", text) activity.
appendText(text) } catch (e: Exception) { Log.
e("client", "Cannot read data", e) } finally { inputStream.
close() outputStream.
close() socket.
close() } }}Inside of the classes’s run() method we just read a message from the client and add it to the screen.
The client class will look like the following:class BluetoothClient(device: BluetoothDevice): Thread() { private val socket = device.
createRfcommSocketToServiceRecord(uuid) override fun run() { Log.
i("client", "Connecting") this.
socket.
connect() Log.
i("client", "Sending") val outputStream = this.
socket.
outputStream val inputStream = this.
socket.
inputStream try { outputStream.
write(message.
toByteArray()) outputStream.
flush() Log.
i("client", "Sent") } catch(e: Exception) { Log.
e("client", "Cannot send", e) } finally { outputStream.
close() inputStream.
close() this.
socket.
close() } }}It simply attempts to access selected device’s service, again identified by the same uuid.
Once connected, the code uses the socket’s output stream to send a message that user typed into the input box.
To enable the server just run the following in the activity’s onCreate() method:BluetoothServerController(this).
start()In order to send a message, the application code should give user the list of available devices and once the user selected device where they want to send a message in question the item select event handler makes the following call:BluetoothClient(device).
start()The variable device in here holds the object of BluetoothDevice class representing device selected by user.
The complete application source code can be downloaded from GitHub.
.