Transferring data between Android devices over bluetooth with Kotlin

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.


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.


inputStream private val outputStream = this.


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.


connect() Log.

i("client", "Sending") val outputStream = this.


outputStream val inputStream = this.


inputStream try { outputStream.


toByteArray()) outputStream.

flush() Log.

i("client", "Sent") } catch(e: Exception) { Log.

e("client", "Cannot send", e) } finally { outputStream.

close() inputStream.

close() this.


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.


. More details

Leave a Reply