skip to Main Content

I am making an app where I need to have my PC and phone communicate via Bluetooth. I have gotten the app and my PC to successfully connect, and my app is receiving an input stream when I send "Hello World" from my PC. However, I cannot seem to figure out how to get a readable string from my input stream. Here is the code I have so far:

private static class BluetoothAcceptThread extends Thread {
        private final Context CONTEXT;
        private final BluetoothAdapter BLUETOOTH_ADAPTER = BluetoothAdapter.getDefaultAdapter();
        private final BluetoothServerSocket BLUETOOTH_SERVER_SOCKET;
        private final java.util.UUID UUID;

        public BluetoothAcceptThread(Context context, java.util.UUID uuid) {
            this.CONTEXT = context;
            this.UUID = uuid;

            BluetoothServerSocket tmp = null;
            try {
                tmp = BLUETOOTH_ADAPTER.listenUsingRfcommWithServiceRecord(
                        CONTEXT.getString(R.string.app_name), UUID);
            } catch (IOException e) {
                e.printStackTrace();
            }
            BLUETOOTH_SERVER_SOCKET = tmp;
        }

        @Override
        public void run() {
            while (true) {
                BluetoothSocket socket = null;
                try {
                    System.out.println("Accepting incoming connections");
                    socket = BLUETOOTH_SERVER_SOCKET.accept();
                    System.out.println("Found connection!");
                } catch (IOException e) {
                    System.out.println(1);
                    e.printStackTrace();
                }

                if (socket != null) {
                    manageConnectedSocket(socket);
                }

                try {
                    assert socket != null;
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        public void cancel() {
            try {
                BLUETOOTH_SERVER_SOCKET.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void manageConnectedSocket(BluetoothSocket socket) {
            try {
                InputStream inputStream = socket.getInputStream();
                while(inputStream.read() == -1) {
                    inputStream = socket.getInputStream();
                }
                String string = CharStreams.toString( new InputStreamReader(inputStream, "UTF-8"));
                System.out.println(string);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

In case it is relevant, here is the test code I am running from my PC:

import bluetooth
import pydbus


def list_connected_devices():
    bus = pydbus.SystemBus()
    mngr = bus.get('org.bluez', '/')

    mngd_objs = mngr.GetManagedObjects()
    connected_devices = []
    for path in mngd_objs:
        con_state = mngd_objs[path].get('org.bluez.Device1', {}).get('Connected', False)
        if con_state:
            addr = mngd_objs[path].get('org.bluez.Device1', {}).get('Address')
            name = mngd_objs[path].get('org.bluez.Device1', {}).get('Name')
            connected_devices.append({'name': name, 'address': addr})

    return connected_devices


def main():
    address = list_connected_devices()[0]["address"]
    uuid = "38b9093c-ff2b-413b-839d-c179b37d8528"
    service_matches = bluetooth.find_service(uuid=uuid, address=address)

    first_match = service_matches[0]
    port = first_match["port"]
    host = first_match["host"]

    sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
    sock.connect((host, port))
    message = input("Enter message to send: ")
    sock.send(message)


if __name__ == '__main__':
    main()

EDIT:

Tried using the solution suggested by Sajeel by using IO utils, and I am getting the error:

W/System.err: java.io.IOException: bt socket closed, read return: -1
W/System.err:     at android.bluetooth.BluetoothSocket.read(BluetoothSocket.java:550)
        at android.bluetooth.BluetoothInputStream.read(BluetoothInputStream.java:88)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:291)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:355)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:181)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.Reader.read(Reader.java:140)
        at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2369)
W/System.err:     at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2348)
        at org.apache.commons.io.IOUtils.copy(IOUtils.java:2325)
        at org.apache.commons.io.IOUtils.copy(IOUtils.java:2273)
        at org.apache.commons.io.IOUtils.toString(IOUtils.java:1041)
        at com.example.app.BluetoothSyncService$BluetoothAcceptThread.manageConnectedSocket(BluetoothSyncService.java:278)
        at com.example.app.BluetoothSyncService$BluetoothAcceptThread.run(BluetoothSyncService.java:251)

EDIT 2:

I motherflipping got it! Here is the code that got it to work:

public void manageConnectedSocket(BluetoothSocket socket) {
        try {
            InputStream inputStream = socket.getInputStream();
            while(inputStream.available() == 0) {
                inputStream = socket.getInputStream();
            }
            int available = inputStream.available();
            byte[] bytes = new byte[available];
            inputStream.read(bytes, 0, available);
            String string = new String(bytes);
            System.out.println(string);

        } catch (IOException e) {
            e.printStackTrace();
        }

2

Answers


  1. Chosen as BEST ANSWER

    Finally figured out the solution. You need to create a Byte Array of the same length of the inputstream's available bytes, then call the .read() method of the inputstream. The input stream will then write the bytes it received to the byte array, which you can then decode into a string.

    public void manageConnectedSocket(BluetoothSocket socket) {
            try {
                InputStream inputStream = socket.getInputStream();
                while(inputStream.available() == 0) {
                    inputStream = socket.getInputStream();
                }
                int available = inputStream.available();
                byte[] bytes = new byte[available];
                inputStream.read(bytes, 0, available);
                String string = new String(bytes);
                System.out.println(string);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    

  2. Try

     String str = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
    

    In order to use IOUtils.toString() add the following things

    In build.gradle app module

        implementation group: 'commons-io', name: 'commons-io', version: '2.5' //Add this line
    

    After that import

    import org.apache.commons.io.IOUtils;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search