0

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();
        }
Chris Ray
  • 133
  • 1
  • 2
  • 8
  • Does this answer your question? [How do I read / convert an InputStream into a String in Java?](https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java) – Sajeel Jul 13 '21 at 23:18

2 Answers2

0

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;
Sajeel
  • 51
  • 1
  • 7
  • I tried using IOUtils and I am getting the error that I listed in my edit. Suggestion? – Chris Ray Jul 14 '21 at 00:25
  • try .available instead of .read like this `while(inputStream.available() == 0);` – Sajeel Jul 14 '21 at 00:52
  • I did that and I still get errors. It appears that it throws the error when my Python code terminates. Maybe it is a problem with the way my PC is sending the data? – Chris Ray Jul 14 '21 at 00:56
  • then try by putting the python code in an infinite loop and check whether the app still throws the same error or not – Sajeel Jul 14 '21 at 01:01
  • I got it now! I just had to read the inputstream into a byte array and then convert it to a string. If you're curious about my solution, you can check my latest edit! Thank you for your help! – Chris Ray Jul 14 '21 at 01:22
  • Put that latest edit in an 'answer' and mark this post as `Solved` by accepting that one – Sajeel Jul 14 '21 at 01:52
0

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();
        }
Chris Ray
  • 133
  • 1
  • 2
  • 8