安卓:蓝牙袜子接收自己的输出

2022-09-01 04:00:57

我有一个应用程序,它通过蓝牙连接到RaspberryPi,并在它接收一些数据时循环相同的数据。

我的连接有一些问题,所以需要这个解决方法才能将我的Android手机连接到RaspberryPi:IOException:读取失败,套接字可能已关闭 - Android 4.3上的蓝牙

由于某种原因,Android手机正在接收自己的输出。字符串“你好树莓。是我,AndroidPhone“以永无止境的循环发送到输出。传入的数据(来自RaspberryPi)也在一个永无止境的循环中读取。

但不知何故,我不仅从RaspberryPi接收数据,而且还通过智能手机发送字符串。这是我的代码:

public class MainActivity extends AppCompatActivity {
    private BluetoothAdapter bluetoothAdapter;
    UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // (...)
        // Only GUI-stuff until this point

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        BluetoothDevice raspberryPi = bluetoothAdapter.getRemoteDevice("B8:27:EB:56:DC:B2");
        BluetoothSocket btSocket;

        try {
            btSocket = raspberryPi.createRfcommSocketToServiceRecord(SERIAL_UUID);
            btSocket.connect();
        } catch (IOException e) {
            Log.e("BTError", e.getMessage());
            // Workaround, found on: https://stackoverflow.com/questions/18657427/ioexception-read-failed-socket-might-closed-bluetooth-on-android-4-3
            try {
                Log.e("BTError", "Trying fallback...");
                btSocket = (BluetoothSocket) raspberryPi.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(raspberryPi, 1);
                btSocket.connect();

                (new Thread(new SendingThread(btSocket))).start();
                (new Thread(new ReceivingThread(btSocket))).start();
            } catch (Exception e2) {
                Log.e("BTError", e2.getMessage());
                Log.e("BTError", "Couldn't establish Bluetooth connection!");
            }
        }
    }

    private class SendingThread extends Thread {
        private OutputStream out;

        public SendingThread(BluetoothSocket btSocket) {
            try {
                out = btSocket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            try {
                int delay = 100000000;
                while (true) {
                    if (delay == 0) {
                        Log.i("WRT", "Written to RaspberryPi");
                        out.write("Hello Raspberry. It's me, AndroidPhone".getBytes());
                        delay = 100000000;
                    }
                    delay--;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private class ReceivingThread extends Thread {
        private InputStream in;

        public ReceivingThread(BluetoothSocket btSocket) {
            try {
                in = btSocket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            int data = 0;
            while (true) {
                try {
                    data = in.read();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Log.i("RCV", String.valueOf((char) data));
            }
        }
    }

在RaspberryPi端,一切看起来都很正常。一个简单的 java 程序启动 Linux 命令,并使用 和 读取/写入文件。这一端唯一相关的行是:rfcomm listen /dev/rfcomm0/dev/rfcomm0FileReaderFileWriter

run {
    // Inside writer-thread
    bluetoothWriter = new BufferedWriter(new FileWriter("/dev/rfcomm0"));
    while(true) {
        bluetoothWriter.write("This is RaspPi");
        bluetoothWriter.flush();
    }
}

run {
    // Inside reader-thread
    bluetoothReader = new BufferedReader(new FileReader("/dev/rfcomm0"));
    while(true) {
        int incData = bluetoothReader.read();
        System.out.print((char) incData);
    }
}

感谢您的帮助!

编辑:仍然没有解决这个问题的方法。我怀疑RaspberryPi以某种方式发送回了它收到的东西。但是,当我禁用它发送任何内容时,智能手机仍然直接接收它发送的内容。


答案 1

我搜索了蓝牙类的来源。从第一眼看,解决方法似乎是合法的。请先试试这个:

if (delay == 0) {
    Log.i("WRT", "Written to RaspberryPi");
    out.write("Hello Raspberry. It's me, AndroidPhone".getBytes());
    out.flush(); // <-- You are not flushing 
    delay = 100000000;
}

信息会粘在你的插座里,让你一遍又一遍地阅读。

如果这不能解决它,我能想到的另一个选项是,以某种方式将套接字初始化为Android设备的套接字。.createRfcommSocket() 方法似乎在创建套接字时为您自己的设备创建一个套接字。我不确定这究竟是如何发生的,但如果Raspberry Pi的状态在异常之后以某种方式被破坏,我想这可能是值得研究的事情。null

另一方面:如果您刚刚启动这两个线程,这是否意味着您不断向 /dev/rfcomm0 发送消息并进行刷新。我建议您更改它,以便通过发回所需的消息而不是一直发送垃圾邮件来对收到的消息做出反应。我不确定这是否是你问题的一部分,但它至少会让调试和开发变得更容易一些。raspyraspy


答案 2

我不确定这是否是您需要的解决方案,因为我不知道您使用的是蓝牙经典还是蓝牙4.0> +,但我为基于文本的BLE和WiFi P2P 2路通信为Android编写了一个(我知道Raspberry Pi能够进行BLE通信),但我不会为BLE通信创建套接字连接, 但我为WiFi P2P做。看一看,我希望它有帮助。它尚未发布,因此您必须克隆/分叉存储库。


推荐