【问题标题】:HTTP get request is missing dataHTTP 获取请求缺少数据
【发布时间】:2012-03-15 13:09:28
【问题描述】:

您好,我在 Android 中遇到了一个奇怪的 HTTP 问题。 我正在尝试从远程服务器获取图片并将其显示在设备上。 如果图片是小JPEG,这不是问题。但是如果图片变大就不行了(只显示图片的一部分)。

这是我的完整演示代码:

public class HTTP_testActivity extends Activity {

private ImageView ivPicture;
private Button btGetImage;  


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ivPicture = (ImageView) findViewById(R.id.ivpiture1);
    btGetImage = (Button) findViewById(R.id.btGetPicture1);
    btGetImage.setOnClickListener(new Button.OnClickListener() 
    {
        public void onClick(View arg0) 
        {
            URI uri;
            try {


                uri = new URI("");
                URLConnection connection =  uri.toURL().openConnection();
                connection.setUseCaches(true);
                connection.connect();

                BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
                Log.d("TEST","Length of Input " +bis.available());
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                Log.d("TEST","Length of Input after wait " +bis.available());
                byte[] data = new byte[640*480*5];
                bis.read(data);
                Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, jdata.length);
                if (bmp != null)
                {
                    ivPicture.setImageBitmap(bmp);
                }
                bis.close();
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            Log.d("TEST", e.getMessage());
            e.printStackTrace();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            Log.d("TEST", e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Log.d("TEST", e.getMessage());
            e.printStackTrace();
        }
        }
    });
}

有人能看出我做错了什么吗? 到目前为止我发现的是: bis.available() 返回的大小永远不会超过 65kb。尽管 InputStream 本身具有正确的长度(在调试器中看到)。

【问题讨论】:

  • 请不要在 UI 线程上进行网络 I/O。当服务器变得有点太慢时,您的应用程序将被操作系统强制关闭。 Andriod上有很多关于如何异步处理网络的教程。
  • 如果您实际阅读了可用的数量 bis 报告,那么 bis.available() 是否会报告更多可用?换句话说,您是否考虑过 while (bis.available() > 0) 循环?除非您事先知道所需的大小,否则您可能需要稍微调整字节缓冲区,在这种情况下,您可以创建足够大的缓冲区以开始并简单地使用每次读取都会增加的起始偏移量。

标签: java android http image http-get


【解决方案1】:

可用()

将返回从输入流中读取的字节数而不阻塞。所以返回的数据是可以从网络中读取而不会阻塞的。

尝试:

            InputStream bis = new InputStream(connection.getInputStream());
            Log.d("TEST","Length of Input " +bis.available());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            int read = 0;
            byte[] buffer = new byte[SIZE_OF_IMAGE];
            byte[] inBuff = new byte[32678]
            while ((read = bis.read(inBuff, 0, 32768)) > 0) {
                   // copy in buffer what have been read
                   // from the input stream
            }

            // close the is
            Bitmap bmp = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);

显然没有更有效的方法可以做到这一点,但可能是一个切入点。如果您需要更多帮助,请告诉我。

编辑:当然,正如人们所建议的那样,您必须避免在 UI 线程中进行阻塞调用。

【讨论】:

  • 谢谢,我现在就试试。我知道阻止 UI Tread 是一个坏主意,但这只是一个概念验证应用程序,以使文件抓取工作。之后它将被放入现有的应用程序中,当然是非阻塞的。
【解决方案2】:

您需要知道的 bis.available() 将始终返回小于 65Kb 的数据,因为最大 IP 数据包大小为 65535 字节。 InputStream 将返回总大小

由于您在任何时间点都只给出了一个 read 语句,因此数据数组将始终小于 65kb。 (即第一个数据包的数据)

您可以做的是使用BitmapFactory.decodeStream(InputStream is) 并提供 InputStream bis,它将读取 Stream 中的所有字节并为您提供位图

已编辑

使用此功能

这将为您提供 InputStream 中的所有字节

 public static byte[] ReadToEOF(InputStream stream) throws Exception
    {
        try {
            ByteArrayOutputStream array = new ByteArrayOutputStream();
            int read = 0;
            byte[] receivedData = new byte[5000];
            while((read = stream.read(receivedData)) > 0)
            {
                array.write(receivedData, 0, read);
                if(!(stream instanceof FileInputStream) && stream.available() == 0)
                {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        // TODO: handle exception
                    }
                    if(stream.available() == 0)
                        break;
                }
            }
            return array.toByteArray();
        } catch (Exception e) {
            // TODO: handle exception
            throw e;
        }
    }

Thread.Sleep 是因为通过 Internet 获取 Next Packet 可能会有一些延迟

【讨论】:

  • 谢谢,但我不能只解码 InpuStream,因为下一步我会从自己的服务器获取 YUV422 图片并对其进行解码。但在我解码之前,我需要字节数组中的整个图片。所以我用这个简单的例子来演示我的问题。
  • 查看我编辑的答案以获取所有字节
  • 在你的while循环中,你应该检查!= -1,它表示文件结束。读取可能会返回 0 个字节,但流中仍有数据要读取。
猜你喜欢
  • 2012-09-11
  • 1970-01-01
  • 2019-09-25
  • 2016-08-24
  • 2015-11-08
  • 2016-06-05
  • 2022-01-19
  • 2018-02-03
  • 2021-06-04
相关资源
最近更新 更多