简体   繁体   中英

Bluetooth transfer App stops after using InputStream.read() with no error

I am trying to make a file transfer Bluetooth app work using these sources:

http://developer.android.com/guide/topics/connectivity/bluetooth.html

https://android.googlesource.com/platform/development/+/25b6aed7b2e01ce7bdc0dfa1a79eaf009ad178fe/samples/BluetoothChat/

When I attempt to get the InputStream bytes using InputStream.read() method this way:

public class ConnectedThread extends Thread {

...(some code here)

public void run(){

        byte[] buffer = new byte[1024];
        int bytes = -1;

        //Keep listening to the InputStream while connected
        while (true){

            try {

                bytes = this.mmInStream.read(buffer);

                //* this part is not reached
                if (bytes==-1){
                    Log.d("NoData:","-1");  
                }

            }
            catch(Exception e){
                Log.d("inStream exception:",e.getMessage());
                break;
            }

        }

    }

...(some code here)

}

The next part of the code ( "if" part in this case) is never reached, nor a Log.D debug output or whatever else I put in following. I just get this message from LogCat:

BluetoothSocket read in: android.net.LocalStocketImpl$SocketInputStream@f7e
                b08 len: 1024

To transfer the data from the Client to the Server I am doing this:

public class MainActivity extends Activity {

...(some code here)

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    clientConnect();
    //serverConnect();

}

...(some code here)

public void clientConnect(){

        Set<BluetoothDevice> devices;

        devices = bConfig.getPairedDevices(); 

        if (devices == null){                   
            return;
        }

        if (devices.size() > 0) {           

            BluetoothDevice device = devices.iterator().next();

            ConnectThread connectTransmit = new ConnectThread(device,bConfig.getBluetoothAdapter(),BluetoothConfig.mUUID);
            connectTransmit.start();

            Toast.makeText(this, "connected", Toast.LENGTH_SHORT).show();

            socket = connectTransmit.mmSocket;
            ConnectedThread connectedThread = new ConnectedThread(socket);

            //write file bytes to the connected thread, so the thread can receive its own input written bytes later
            File file_to_transfer = new File(Environment.getExternalStorageDirectory() + "/txtTransfer.txt");           

            //get bytes from our File
            int size = (int) file_to_transfer.length();
            byte[] bytes = new byte[size];

            try {

                //14b are read succesfully, the whole text file 
                BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file_to_transfer));
                buf.read(bytes,0,bytes.length);
                buf.close();                

            }catch (FileNotFoundException e){
                Log.d("FileNotFoundException:",e.getMessage());
            }catch (IOException e){ 
                Log.d("IOException:",e.getMessage());
            }

            //send the data to the server
            connectedThread.start();
            connectedThread.write(bytes);
            //connectedThread.cancel();

        }

    }

...(some code here)

}

The AcceptThread (Server part of the implementation) works, because when I run the client part to connect and then transfer the data, while debuging in the device the LogCat on the Server part activates and reaches the run method of the thread, where I call the ConnectedThread implementation but then after it "apparently" reads the bytes but it gets stuck on LogCat with no error.

Please let me know what can I do to finish reading the bytes to move to the next part of the flow.

Thank you

You're blocked waiting for more input.

The part labelled ... (some code here) should be inside the read loop, after the test for end of stream. NB If read() returns -1 it doesn't mean 'no data', it means end of stream, and you should close the socket and break out of the read loop. Otherwise you should then go on to process the data you've just read. At present you just read and ignore all input until end of stream, which is pointless. At best you can only process the last partial buffer, and you won't know how long it was.

In your client code you should probably keep the connectedThread object alive a while longer. Might be that once the if clause closes and it goes out of scope (not quite sure what happens with GC and all) the write just doesn't happen and your connection is not closed but not used either.

Calling flush() on the mmOutStream inside the connectedThread after the write might help also.

Like @EJP suggested, you should put something inside your read loop.

For the sake of debugging you could add this.wait(1000); 为了调试你可以添加this.wait(1000); immediately after your write in the client code.

In my opinion You should verify if something is in buffer before reading. reading from stream is blocking operation so aplication will hang until somehing data appear. How can I check if an InputStream is empty without reading from it?

Try changing your run method to this:

public void run(){
    byte[] buffer = new byte[1024];
    int bytesRead = 0;
    final int shortSleepTime = 1000;
    final int longSleepTime = 5000;
    int emptyReadCounter = 0;
    int sleepCounter = 0;
    int currentSleepTime = shortSleepTime;

    //Keep listening to the InputStream while connected
    while (bytesRead >= 0){
        try {

            // if available() returns 0, there is nothing to read yet
            if (this.mmInStream.available() != 0){
                bytesRead = this.mmInStream.read(buffer);

                // Check if we need to reset the sleep counters
                if (emptyReadCounter != 0){
                    emptyReadCounter = 0;
                    sleepCounter = 0;
                    currentSleepTime = shortSleepTime;

                    // We can also do anything else dependent on just waking up
                    // from a sleep cycle in this block
                }


                // Do something with my now full buffer
                // Remember not to process more than 
                // 'bytesRead' bytes from my buffer because the
                // rest could be filled with crap left over from
                // the last iteration
            } else {                
                // Three consecutive empty reads means sleep
                if (emptyReadCounter++ >= 3){                       
                    if (currentSleepTime != longSleepTime && sleepCounter++ >= 3){
                        currentSleepTime = longSleepTime;
                    }
                    Thread.sleep(currentSleepTime);
                }
            }
        }
        catch(Exception e){
            Log.d("inStream exception:",e.getMessage());
            break;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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