9

Is it possible to implement a timeout in an inputstream.read() function from a BluetoothSocket in Android?

I've tried using Thread.sleep() but this only pauses my activity.

---Update---

I had an idea, make 2 thread code herereads(t1 & t2) where each thread interrupt other, one of them(t1) do a sleep(5000) then interrupt the other thread(t2), from the other side the other thread(t2) if in read the inputstream detects some character as 0x0D interrupt the other thread(t1), but here is my question, does anybody can help me? because i didn't use interrupt() method of threads, I hope someone can help me, thank you...

---Update---



        public void run(){
        while(true){
            try {
            char r;
            String respuesta = "";
            while (true) {
                    r = (char) mmInStream.read();
                respuesta += r;
                if (r == 0x3e) {
                break;
                    }
                }
            respuesta = respuesta.replaceAll(" ", "");
            Log.d("respuesta", respuesta);
            rHandler.obtainMessage(MESSAGE_READ, -1, -1, respuesta).sendToTarget();
            } catch (IOException readException) {
            Log.e("ServicioGeneral", "Error de lectura", readException);
            this.interrupt();
            connectionLost();
            // posibly break();
            }
        }
    }

This is my implementation when something comes in a different Thread, the problem is that the timeout will be reached if i dont get the 0x3e character from de mmInStream.

I supposed that in the second example i must use a notifyAll(), but, when do I have to start the readThread()?

Thank you, @weeman

kaushik parmar
  • 805
  • 6
  • 19
  • As far as the API goes, I didn't encounter a method that does that... Perhaps there is some reflective way to do it...!? – TacB0sS May 09 '12 at 20:18
  • Both Bluetooth Socket and inputstream don't have any method to implement a timeout. That is my problem i've tried with Threads and handlers but couldn't get implemented yet... Thanks for your answer – Poperto Arcadio Buendía May 11 '12 at 14:52
  • For suppressing spaces in a string you can use "Trim()" instead of "replaceAll(" ", "")" – An-droid Feb 06 '15 at 10:10

2 Answers2

9

You could do something like this:

InputStream in = someBluetoothSocket.getInputStream();
int timeout = 0;
int maxTimeout = 8; // leads to a timeout of 2 seconds
int available = 0;

while((available = in.available()) == 0 && timeout < maxTimeout) {
    timeout++;
    // throws interrupted exception
    Thread.sleep(250);
}

byte[] read = new byte[available];
in.read(read);

This way you are able to initially read from a stream with a specific timeout. If u want to implement a timeout at any time of reading you can try something like this:

Thread readThread = new ReadThread(); // being a thread you use to read from an InputStream
try {
   synchronized (readThread) {
      // edit: start readThread here
      readThread.start();
      readThread.wait(timeOutInMilliSeconds);
   }
catch (InterruptedException e) {}

using this you may need some kind of event handler to notify your application if the thread actually read something from the input stream.

I hope that helps!

----edit:

I implemented an example without using any handlers.

Socket s = new Socket("localhost", 8080);
    final InputStream in = s.getInputStream();

    Thread readThread = new Thread(new Runnable() {
        public void run() {
            int read = 0;
            try {
                while((read = in.read()) >= 0) {
                    System.out.println(new String(new byte[]{ (byte) read }));
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });

    synchronized (readThread) {
        readThread.start();
        try {
            readThread.wait(2000);

            if(readThread.isAlive()) {
                                    // probably really not good practice!
                in.close();
                System.out.println("Timeout exceeded!");
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
jobnz
  • 398
  • 3
  • 10
  • Very nice timeouts implementation but I dont get it to make it work in my code i've updated my answer if you can give me a hand... Thanks... by the way you put,
    
        byte[available] read=new byte[available]
    
    and is
    
    
        byte[] read=new byte[available];
    
    
    – Poperto Arcadio Buendía May 14 '12 at 16:49
  • oh, yes. You are right. I'm going to change that and try to give an answer to your updated question. – jobnz May 14 '12 at 21:36
  • Thanks @weeman after read the code I understand how this timeout works and i could implement one if i didn't receive response from my microcontroller, thanks... – Poperto Arcadio Buendía May 16 '12 at 15:21
1

A Kotlin extension function for socket read with timeout:

fun InputStream.read(
  buffer: ByteArray,
  offset: Int,
  length: Int,
  timeout: Long
): Int = runBlocking {
    val readAsync = async {
        if (available() > 0) read(buffer, offset, length) else 0
    }
    var byteCount = 0
    var retries = 3
    while (byteCount == 0 && retries > 0) {
        withTimeout(timeout) {
            byteCount = readAsync.await()
        }
        delay(timeout)
        retries--
    }
    byteCount
}
NSaran
  • 561
  • 3
  • 19