Android: 如何通过蓝牙连接从输入流中读取字符串?

Android: How to read a string from input stream via bluetooth connection?

我正在制作一个应用程序,我需要让我的 PC 和 phone 通过蓝牙进行通信。我已经让应用程序和我的电脑成功连接,当我从我的电脑发送“Hello World”时,我的应用程序正在接收输入流。但是,我似乎无法弄清楚如何从输入流中获取可读字符串。这是我到目前为止的代码:

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();
            }
        }
    }

如果相关,这是我 运行 从我的 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()

编辑:

尝试使用 Sajeel 建议的解决方案,使用 IO utils,但出现错误:

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)

编辑 2:

我妈搞定了!这是让它工作的代码:

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();
        }

尝试

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

为了使用IOUtils.toString()添加以下内容

build.gradle 应用程序模块中

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

之后import

import org.apache.commons.io.IOUtils;

终于找到解决办法了。您需要创建一个与输入流的可用字节长度相同的字节数组,然后调用输入流的 .read() 方法。然后输入流会将接收到的字节写入字节数组,然后您可以将其解码为字符串。

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();
        }