我正在开发一个通过BluetoothSocket
接收图像的安卓应用程序,我试图通过使用BitmapFactory.decodeStream()
方法检索其Bitmap
,如下所示:
// Create BluetoothSocket socket and connect
// ...
// Get input stream
InputStream inputStream = socket.getInputStream();
// Get image bitmap
Bitmap bmp = BitmapFactory.decodeStream(inputStream);
所发生的情况是,应用程序被困在BitmapFactory.decodeStream()
上。要永远停止应用程序挂起,我必须从远程设备手动关闭套接字,只有在此之后图像才会被成功解码和返回,但对于我的应用程序来说,这不是一个可行的解决方案,因为我希望以编程方式传输图像。我尝试过的另一件事是创建一个单独的Thread
并在其中调用decodeStream()
,然后用硬编码的时间调用Thread.start()
,然后用硬编码的时间等待,然后再终止线程。这是可行的,但我想避免这样做有两个原因:
我查看了文档,希望在解码图像之前找到一种方法来初步设置预期的图像大小,这样应用程序就可以知道数据何时被正确地接收到了,比如:
// Estimate length of expected data (size of image in bytes)
byte[] numOfBytes = new byte[inputStream.available()];
inputStream.read(numOfBytes)
// Set preliminary options
BitmapFactory.Options options = new BitmapFactory.Options();
options.setExpectedImageSize(numOfBytes) // what I would ideally want: set fixed number of bytes
// to let the BitmapFactory.decodeStream() method know when
// the decoding is over
// Get image bitmap
Bitmap bmp = BitmapFactory.decodeStream(inputStream, null, options);
但这样的程序似乎并不存在。
我有办法做到这一点吗?
码
服务器端(C#)
// Create bluetooth socket
// ...
DataWriter writer = new DataWriter(socket.OutputStream);
// Send image byte array
writer.WriteBytes(imageByteArray);
await writer.StoreAsync();
await writer.FlushAsync();
writer.Dispose();
socket.Dispose();
客户端(Java)
// Create bluetooth socket and connect
// ...
InputStream inputStream = socket.getInputStream();
Bitmap bmp = BitmapFactory.decodeStream(inputStream);
return bmp;
已发送:
已收到:
发布于 2022-01-26 09:57:07
当BitmapFactory.decodeStream()准备就绪时,它将关闭流。因此插座也会关闭。你说它挂了?我们..。嗯嗯。嗯。
这就是为什么我早些时候说过,服务器应该在发送文件之后关闭套接字。是什么原因导致我的图像在传输期间损坏通过蓝牙RFCOMM使用FTP?
如果希望在发送/接收图片后保持连接打开,则不能使用BitmapFactory.decodeStream()。-
希望能在解码图像之前,找到一种初步设定图像大小的方法,
嗯,这是相当标准的。您让服务器首先发送一个整数(4个字节),指示以下字节的长度/数量。
客户端首先读取该整数,并可以创建一个大小合适的字节数组,将文件的接收字节放在其中。然后可以使用BitmapFactory.decodeByteArray()。(或者类似的事情)。
发布于 2022-01-26 14:26:34
如果decodeStream
没有完成,这很可能意味着它试图读取的InputStream
已经阻塞。这意味着它还没有收到预期的数据。
还有另一个可能的解释:服务器可能发送格式错误的图像,导致解码器被卡在客户端。Java 5图像解码器中的一个例子.很久很久以前..。是CVE-2006-6745。可能还有更近期的。
显然,不同于Java图像解码器类,Android的decodeStream
不调用这意味着,除了检查它返回的decodeStream
的值之外,没有任何方法可以判断调用是否已经完成。javadoc指出:
“如果输入流为null,或者不能用于解码位图,则函数返回null。在读取编码数据之后,该流的位置将一直保持在原来的位置。”
但我觉得你真的没抓住重点。如果我错了,请纠正我,但实际上您要做的是阻止客户端大小阻塞服务器,反之亦然。解决方案是使用计时器或超时。
decoderStream
花费的时间过长。decoderStream
调用应该返回null
。(至少,这就是文档所暗示的。)您解决这个问题的方法如下所示:
byte[] numOfBytes = new byte[inputStream.available()];
inputStream.read(numOfBytes);
BitmapFactory.Options options = new BitmapFactory.Options();
options.setExpectedImageSize(numOfBytes);
Bitmap bmp = BitmapFactory.decodeStream(inputStream, null, options);
这种做法存在致命的缺陷。
InputStream.available
上调用,只有才能告诉您有多少数据可以在不阻塞的情况下读取。基本上,这是已经接收到客户端的内核TCP/IP缓冲区的数据。可能不会是整个画面。
基本上,调用InputStream.available
很少是正确的。(海事组织,如果他们反对的话,那是个好主意.虽然我怀疑他们会这样做。)inputStream.read(numOfBytes)
不会读取整个图像。numOfBytes
中,您不会做任何有用的事情。Options
中没有设置“预期图像大小”的方法。https://stackoverflow.com/questions/70861089
复制相似问题