在 Android 中的 BluetoothSocket inputstream.read() 中实现超时
Posted
技术标签:
【中文标题】在 Android 中的 BluetoothSocket inputstream.read() 中实现超时【英文标题】:Implement a timeout in BluetoothSocket inputstream.read() in Android 【发布时间】:2012-05-18 08:42:00 【问题描述】:是否可以在 android 中的 BluetoothSocket 的 inputstream.read() 函数中实现超时?
我尝试过使用 Thread.sleep() 但这只会暂停我的活动。
---更新---
我有一个想法,在此处创建 2 个线程代码(t1 和 t2),其中每个线程中断其他线程,其中一个线程(t1)执行睡眠(5000)然后中断另一个线程(t2),从另一侧其他线程(t2)如果在读取输入流中检测到某些字符为 0x0D 中断其他线程(t1),但这是我的问题,有人可以帮助我吗?因为我没有使用线程的interrupt()方法,希望有人能帮助我,谢谢...
---更新---
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();
这是我在不同线程中的实现,问题是如果我没有从 de mmInStream 获得 0x3e 字符,则会达到超时。
我认为在第二个示例中我必须使用 notifyAll(),但是,我什么时候必须启动 readThread()?
谢谢你,@weeman
【问题讨论】:
就 API 而言,我没有遇到这样的方法......也许有一些反思的方式来做到这一点......!? 蓝牙 Socket 和输入流都没有任何方法来实现超时。这是我尝试使用线程和处理程序但无法实现的问题...感谢您的回答 为了抑制字符串中的空格,您可以使用 "Trim()" 而不是 "replaceAll(" ", "")" 【参考方案1】:一个 Kotlin 扩展函数,用于超时读取套接字:
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
【讨论】:
【参考方案2】:你可以这样做:
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);
通过这种方式,您可以从具有特定超时的流中进行初始读取。如果你想在阅读的任何时候实现超时,你可以尝试这样的事情:
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)
如果线程实际上从输入流中读取了某些内容,您可能需要某种事件处理程序来通知您的应用程序。
希望对你有帮助!
----编辑:
我在没有使用任何处理程序的情况下实现了一个示例。
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();
【讨论】:
非常好的超时实现,但我没有让它在我的代码中工作,如果你能帮我,我已经更新了我的答案......谢谢......顺便说一句, byte[available] read=new byte[available]
并且是 byte[] read=new byte[available];
哦,是的。你说的对。我将更改它并尝试回答您更新的问题。
感谢@weeman 在阅读完代码后我了解了这个超时是如何工作的,如果我没有收到来自我的微控制器的响应,我可以实现一个,谢谢...以上是关于在 Android 中的 BluetoothSocket inputstream.read() 中实现超时的主要内容,如果未能解决你的问题,请参考以下文章
android ViewPager+Fragment 如何在ViewPager的Activity中获取Fragment中的控件对象