Bluetooth Transfer application crashes after using InputStream.read () without error

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

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

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

When I try to get bytes of an InputStream using the method InputStream.read()

like this:

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 piece of code ( "if"

in this case) will never be reached, as well as debug output Log.D

or whatever I added. I just get this message from LogCat:

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

      

To transfer data from the Client to the Server, I do 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)

}

      

AcceptThread

(the server side of the implementation) works because when I start the client side to connect and transfer data, when debugging in the device, the LogCat on the server side gets triggered and reaches the thread startup method where I call the implementation ConnectedThread

, but then after that "apparently" reads bytes but it gets stuck in LogCat with no error.

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

thank

+3


source to share


4 answers


You are locked out waiting for more input.



The labeled part ... (some code here)

must be inside the read loop after the end-of-stream test. NB If it read()

returns -1, it does not mean "no data", it means the end of the stream and you must close the socket and exit the read loop. Otherwise, you must continue to process the data you just read. Currently, you just read and ignore all input until the end of the stream, which is pointless. At best, you can only process the last partial buffer, and you won't know how long it was.

+5


source


In your client code, you should probably keep the connectedThread object even longer. Maybe after the if clause closes and goes out of scope (not really sure what's going on with the GC and that's it) the write just doesn't happen and your connection isn't closed but not used.

Calling flush () on mmOutStream inside a connectedThread after writing can also help.



Like @EJP you have to put something inside your read loop.

Edit: For debugging, you can add this.wait(1000);

right after write to client code.

+1


source


In my opinion, you should check if something is in the buffer before reading. reading from a stream is a blocking operation, so the application will hang until any data is available. How can I check if an InputStream is empty without reading it?

+1


source


Try changing your execution method like 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;
        }
    }
}

      

+1


source







All Articles