简体   繁体   English

Android Bluetooth Inputstream.read从不接收数据

[英]Android Bluetooth Inputstream.read never receiving data

I am making a game for Android, in which two devices connect and then trade a small amount of data, then disconnect and use that data. 我正在为Android开发游戏,其中两个设备先连接,然后交换少量数据,然后断开连接并使用这些数据。 I started with the Bluetooth Chat example. 我从蓝牙聊天示例开始。 At this point, I have it mostly working, but some (most) times, one of the devices never receives any data. 在这一点上,我可以正常工作,但是有时(大多数),其中一台设备从未收到任何数据。 This is the same app on both devices, so the send and receive code for both is the same. 这是两个设备上的相同应用程序,因此两者的发送和接收代码相同。 I am connecting like this: 我这样连接:

    public BluetoothClientThread(BluetoothDevice get_device,boolean secure){
        BluetoothSocket temp=null;
        device=get_device;
        socket_type=secure?"Secure":"Insecure";

        try{
            if(secure){
                temp=device.createRfcommSocketToServiceRecord(UUID_SECURE);
            }
            else{
                temp=device.createRfcommSocketToServiceRecord(UUID_INSECURE);
            }
        }
        catch(IOException e){
            StorageManager.error_log_add(context,TAG,"create() on "+socket_type+" client socket failed.",e);
        }

        socket=temp;
    }

    public void run(){
        bluetooth_adapter.cancelDiscovery();

        try{
            socket.connect();
        }
        catch(IOException e){
            StorageManager.error_log_add(context,TAG,"Connection failed.",e);

            try{
                socket.close();
            }
            catch(IOException ioe){
                StorageManager.error_log_add(context,TAG,"close() on "+socket_type+" client socket failed during connection failure.",ioe);
            }

            connection_failed();

            return;
        }

        synchronized(BluetoothService.this){
            bluetooth_client_thread=null;
        }

        connected(socket,device,socket_type,false);
    }

Once connected, I grab the socket's getInputStream() and getOutputStream(). 连接后,我将获取套接字的getInputStream()和getOutputStream()。 I then use the following code to read input on the socket: 然后,我使用以下代码读取套接字上的输入:

    public void run(){
        String packet="";

        while(true){
            try{
                int get_byte=input.read();
                char get_char=(char)get_byte;

                if(get_char!='\u0003'){
                    StorageManager.error_log_add(context,"BluetoothService","Adding packet raw data: \""+get_char+"\"",null);
                    packet+=get_char;
                }
                else{
                    StorageManager.error_log_add(context,"BluetoothService","Packet received:\n"+packet,null);
                    handler.obtainMessage(Activity_Battle_Menu.HANDLER_READ,packet).sendToTarget();
                    packet="";
                }

                if(done && they_done){
                    handler.obtainMessage(Activity_Battle_Menu.HANDLER_READY).sendToTarget();
                }
            }
            catch(IOException e){
                StorageManager.error_log_add(context,TAG,"Connection lost.",e);

                connection_lost();

                break;
            }
        }
    }

It reads data one byte at a time, appending the bytes to a packet String. 它一次读取一个字节的数据,然后将字节附加到数据包字符串中。 When the ETX character is reached (which I stick on the end of everything when I send it), a complete packet has been received, and is passed to the activity via handler, where it is acted upon. 到达ETX字符时(发送时我会粘贴在所有内容的结尾),这表示已收到完整的数据包,并通过处理程序将其传递给活动,并对其进行操作。 Here is my writing code: 这是我的编写代码:

    public void write(byte[] buffer){
        try{
            StorageManager.error_log_add(context,"BluetoothService","Writing data:\n"+new String(buffer),null);

            output.write(buffer);
        }
        catch(IOException e){
            StorageManager.error_log_add(context,TAG,"write() on "+socket_type+" connected socket failed.",e);
        }
    }

As you can see, I write to a log when a data "packet" is sent, when a byte is received, and when a whole "packet" has been received. 如您所见,当发送数据“包”,接收到字节以及接收到整个“包”时,我将写入日志。

I'm not sure if any of this is relevant, but: I am testing this with a Nook Color with Cyanogenmod 7.1 (Android 2.3.7) and Android x86 running in VirtualBox (Android 2.3.5). 我不确定是否有任何相关内容,但是:我正在使用带有Cyanogenmod 7.1(Android 2.3.7)和在VirtualBox(Android 2.3.5)中运行的Android x86的Nook Color进行测试。 My app's minSdkVersion is 8 (Android 2.2). 我的应用程序的minSdkVersion是8(Android 2.2)。 For the Android running on my computer, I'm using a Rocketfish USB Bluetooth adapter. 对于计算机上运行的Android,我正在使用Rocketfish USB蓝牙适配器。

There are supposed to be two packets of data sent by each instance. 每个实例应该发送两个数据包。 First, a data packet holding all of the needed game data is sent. 首先,发送包含所有需要的游戏数据的数据包。 When the other instance's game data is received, the app sets its own boolean done to true. 收到其他实例的游戏数据后,应用程序会将自己的布尔值done设置为true。 It also sends a "done" packet to the other instance. 它还将“完成”数据包发送到另一个实例。 Thus, once both instances are done, and know the other is done, we know all data has been sent and received, and they both disconnect/stop their Bluetooth threads and act on the data. 因此,一旦两个实例都完成了,并且知道另一个已经完成,我们就知道所有数据都已发送和接收,并且它们都断开/停止了它们的蓝牙线程并对该数据执行操作。

Since I have it logging on both devices when data is sent and received, the logs tell me a story of what is going on. 由于我在发送和接收数据时都在两个设备上都进行了登录,因此日志告诉了我发生了什么。

-First, I start both games and go to the Bluetooth activity (obviously). -首先,我同时启动两个游戏和进行蓝牙活动(显然)。

-Next, I connect to the Nook instance from the emulated instance. -接下来,我从仿真实例连接到Nook实例。

-The emulated instance sends its game data packet. -模拟实例发送其游戏数据包。

-The Nook instance receives the emulated instance's game data, and sends its own (sometimes these two are switched in order, just because they happen asynchronously). -Nook实例接收模拟实例的游戏数据,并发送自己的数据(有时这两个是按顺序切换的,因为它们是异步发生的)。

-Since it received a game data packet, the Nook instance now sends its "done" packet. -由于Nook实例收到了游戏数据包,因此现在发送其“完成”包。

-That is it. -这就对了。 The emulated instance never receives either packet. 仿真实例从不接收任何数据包。 It never even receives a single byte, and the input.read() just blocks, waiting for input that never arrives (like it should). 它甚至从不接收单个字节,并且input.read()只是阻塞,等待永不到达的输入(像应该这样)。

So that is my problem. 这就是我的问题。 It seems that one of two things is happening: 似乎正在发生以下两种情况之一:

  1. The data never gets sent by output.write() on the Nook instance, even though it does not throw any exception, and the log verifies that it gets called. 即使Nook实例上没有抛出任何异常,该数据也永远不会通过output.write()发送,并且日志会验证它是否被调用。

  2. The data never gets received by input.read() on the emulated instance. 数据永远不会在模拟实例上被input.read()接收。 Maybe it gets lost in transmission? 也许在传输中迷路了?

As far as I can tell, my code is rock solid. 据我所知,我的代码牢不可破。 The problem seems to be Bluetooth-related. 问题似乎与蓝牙有关。 Maybe one or both Android instance has a screwy Bluetooth setup? 也许一个或两个Android实例都设置了错误的蓝牙设置?

I also want to add that every rare once in a while (maybe 1/15 times), all of the packets are sent and received properly, and the game proceeds as it should. 我还想补充一下,每隔一段时间(可能是1/15次),每一次稀有,所有数据包都会正确发送和接收,并且游戏会按预期进行。 So whatever is wrong only USUALLY happens, but not always. 因此,无论什么错误,只有通常会发生,但并非总是如此。

I got access to another Android device with Bluetooth. 我可以使用蓝牙访问另一个Android设备。 I've since tested my game, and it connects and the devices trade data correctly. 从那以后,我就测试了我的游戏,它可以连接并且设备可以正确地交易数据。 I've found several other bugs with my program that occur after the Bluetooth stuff, but that is neither here nor there! 我在蓝牙程序之后发现了程序中的其他一些bug,但这不是那里还是那里!

The Nook Color from before and an HTC Status are what worked together. 之前的Nook Color和HTC Status是一起工作的。 I'm officially concluding, then, that I have a faulty Bluetooth adapter on my computer. 因此,我正式断定我的计算机上的蓝牙适配器有故障。 The code posted above works nicely enough. 上面发布的代码效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM