Java Android:ThreadSafeClientConnManager下载图像时出现错误

Java Android:ThreadSafeClientConnManager下载图像时出现错误,java,android,thread-safety,httpclient,bugfender,Java,Android,Thread Safety,Httpclient,Bugfender,对于我当前的应用程序,我从不同的“事件”中收集图像 西班牙的“供应商” Bitmap bmp=null; HttpGet httpRequest = new HttpGet(strURL); long t = System.currentTimeMillis(); HttpResponse response = (HttpResponse) httpclient.execute(httpRequest); Log.i(TAG, "Image ["+ strURL + "]

对于我当前的应用程序,我从不同的“事件”中收集图像 西班牙的“供应商”

  Bitmap bmp=null;
  HttpGet httpRequest = new HttpGet(strURL);

  long t = System.currentTimeMillis();
  HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
  Log.i(TAG, "Image ["+ strURL + "] fetched in [" + (System.currentTimeMillis()-t) + "ms]");

     HttpEntity entity = response.getEntity();
     InputStream instream = entity.getContent();
     bmp = BitmapFactory.decodeStream(instream);

     return bmp;
然而,当我从salir.com下载图像时,我得到以下信息 logcat输出:

13970     Gallery_Activity  I  Fetching image 2/8 URL: http://media.salir.com/_images_/verticales/a/0/1/0/2540-los_inmortales_la_trattoria-marc_aureli_27_29_no.jpg
13970     ServiceHttpRequest  I  Image [http://media.salir.com/_images_/verticales/a/0/1/0/2540-los_inmortales_la_trattoria-marc_aureli_27_29_no.jpg] fetched in [146ms]
13970     skia  D  --- decoder->decode returned false
搜索该错误消息并没有提供太多有用的结果

有人知道问题出在哪里吗

格雷西亚斯


更新1:

在多问了一点并测试了不同的东西之后,我发现问题似乎出在其他地方。即使我的logcat输出显示

13970     ServiceHttpRequest  I  Image [http://media.salir.com/_images_/verticales/a/0/1/0/2540-los_inmortales_la_trattoria-marc_aureli_27_29_no.jpg] fetched in [146ms]
getContentLength(): 93288
哪个是正确的图像长度(以字节为单位)。流或HTTP连接似乎有问题

我的原始代码(上面)正在利用。如果我只使用一个简单的
URLConnection
来替换它,它将非常有效:

URL url = new URL(strURL);
URLConnection conn = url.openConnection();
conn.connect();
InputStream instream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(instream);
所以,我现在想知道为什么我的
ThreadSafeClientConnManager
与我的所有其他连接(主要是交换
JSONObject
)都能完美地工作(至少看起来是这样),而与一些特定网站(例如salir.com,但对于大多数其他网站,它都能工作)。是否缺少HTTP参数

我当前的设置是:

HttpParams parameters = new BasicHttpParams();
HttpProtocolParams.setVersion(parameters, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(parameters, HTTP.UTF_8);
HttpProtocolParams.setUseExpectContinue(parameters, false); // some webservers have problems if this is set to true
ConnManagerParams.setMaxTotalConnections(parameters, MAX_TOTAL_CONNECTIONS);
HttpConnectionParams.setConnectionTimeout(parameters, CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(parameters, SOCKET_TIMEOUT);

SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", 
     PlainSocketFactory.getSocketFactory(), HTTP_PORT));

ClientConnectionManager conMgr = new ThreadSafeClientConnManager(parameters,schReg);

DefaultHttpClient http_client = new DefaultHttpClient(conMgr, parameters);

更新2:

现在,奇怪的是,它实际上与
ThreadSafeClientConnManager
-有时-一起工作。如果我连续几次尝试下载图像并对其进行解码,在15-30次尝试后可能会奏效。很奇怪

我希望有一个解决方案,因为我更喜欢使用
ThreadSafeClientConnManager
而不是
URLConnection


更新3:


正如下面Mike Mosher所建议的,使用解码错误似乎不再出现。但是现在,尽管比以前少了,但我得到了一个
SkImageDecoder::Factory返回的null
错误。

我也遇到了类似的问题,根问题是由于请求某些图像时超时。我改用a,从那以后就没有问题了。希望这对Stefan有所帮助

我也遇到过同样的问题,在网上搜索时没有发现太多。很多人都有过这个问题,但解决这个问题的答案并不多

我使用URLConnection获取图像,但我发现问题不在于下载,而是BitmapFactory.decodeStream在解码图像时遇到问题

我更改了代码以反映您的原始代码(使用httpRequest)。我做了一个改变,我发现在(感谢尼利斯)。您需要添加“BufferedHttpEntity bufHttpEntity=new BufferedHttpEntity(entity);”

这是我以前的代码:

        conn = (HttpURLConnection) bitmapUrl.openConnection(); 
        conn.connect();
        is = conn.getInputStream();
        //bis = new BufferedInputStream(is);
        //bm = BitmapFactory.decodeStream(bis);
        bm = BitmapFactory.decodeStream(is);
而她的代码是有效的:

            HttpGet httpRequest = null;

    try {
        httpRequest = new HttpGet(bitmapUrl.toURI());
    } catch (URISyntaxException e) {
        e.printStackTrace();
    }

    HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);

        HttpEntity entity = response.getEntity();
        BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity); 
        InputStream instream = bufHttpEntity.getContent();
        bm = BitmapFactory.decodeStream(instream);
正如我所说的,我有一个页面可以下载大约40张图片,你可以刷新以查看最新的照片。如果出现“decoder->decode returned false error”(译码器->解码返回错误),我几乎有一半失败。使用上述代码,我没有遇到任何问题


谢谢

我现在已经尝试了不同的方法,你使用的简单URL连接似乎对你有用,Mike Mosher使用的方法,还有这种方法[它们都会导致解码返回false]


但是,如果我将图像转换为PNG,所有方法都可以正常工作!!但是我尝试将图像放在我的工作ftp主页上,然后使用简单的解决方案将所有jpg加载正常…因此,出于某种原因,如果服务器速度不够快,它似乎会在jpg文件真正完全下载之前解析这些文件。

我的解决方案不是使用BitmapFactory.decodeStream()因为在我看来,它使用的是SKIA解码器,有时看起来有点不稳定。你可以试试这样的方法

    Bitmap bitmap = null;
    InputStream in = null;
    BufferedOutputStream out = null;
    try {
            in = new BufferedInputStream(new URL(url).openStream(),
                     IO_BUFFER_SIZE);

            final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
            out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
            copy(in, out);
            out.flush();

            final byte[] data = dataStream.toByteArray();
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);


   } catch (......){

   }        
对于copy()函数


IO\u BUFFER\u SIZE
是一个值为4*1024的常量整数。

我在尝试从字节数组解码图像时遇到了完全相同的问题。经过一些实验后,解决方案似乎是在BitmapFactory的选项中分配一些临时存储。请尝试:

Options options = new Options();
options.inTempStorage = new byte[256];
Bitmap newMapBitmap = BitmapFactory.decodeStream(instream, null, options);

如果问题无法立即解决,请尝试增加临时数组的大小。我认为大型位图文件需要更大的缓冲区进行解码。

在选项中设置默认缓冲区确实有助于解决有关BitmapFactory的一些内存不足问题,但肯定不能涵盖所有问题。潜在问题似乎是某种类型的检索位图或位图头时超时。我正在将流写入临时文件,然后将临时文件传递给工作正常的BitmapFactory。

也尝试添加此选项

opt.inPurgeable = true;
HttpURLConnection hConn=null;
hConn=openHttpConnection(szUrl);
setRequestMethod(“GET”);
setRequestProperty(“用户代理”,szUserAgent);
hConn.setRequestProperty(“接受”,szapt);
setRequestProperty(“接受字符集”,szCharset);
hConn.setInstanceFollowRedirects(true);
hConn.setUseCaches(true);
hConn.setChunkedStreamingMode(8*1024);
hConn.setDoInput(true);
hConn.setConnectTimeout(60*1000);
hConn.setReadTimeout(60*1000);
hConn.connect();
InputStream bmpIs=hConn.getInputStream();
BufferedInputStream bmpBis=新的BufferedInputStream(BMPI);
位图bmpThumb=null;
BitmapFactory.Options bfOpt=新的BitmapFactory.Options();
bopt.inScaled=真;
bopt.inSampleSize=2;
bopt.inpurgable=true;
bmpThumb=BitmapFactory.decodeStream(bmpBis,null,bfOpt);
if(bmpThumb==null)
{

对于(inti=0;i这是一个Android错误。您的代码还可以。 “Android的解码器目前不支持解码时的部分数据。” 如果你在实体中得到图像,它可能是一个部分输入流,而android目前无法处理这个问题

解决方案是从此线程使用FlushedInputStream:
我遇到了这个错误“
opt.inPurgeable = true;
HttpURLConnection hConn = null;
        hConn = openHttpConnection(szUrl);

        hConn.setRequestMethod("GET");  
        hConn.setRequestProperty("User-Agent",szUserAgent);
        hConn.setRequestProperty("Accept",szAccept);
        hConn.setRequestProperty("Accept-Charset",szCharset);

        hConn.setInstanceFollowRedirects(true);
        hConn.setUseCaches(true);
        hConn.setChunkedStreamingMode(8*1024);
        hConn.setDoInput(true);
        hConn.setConnectTimeout(60*1000);
        hConn.setReadTimeout(60*1000);
        hConn.connect();


        InputStream bmpIs = hConn.getInputStream();
        BufferedInputStream bmpBis = new BufferedInputStream(bmpIs); 
        Bitmap bmpThumb = null;

        BitmapFactory.Options bfOpt = new BitmapFactory.Options();

        bfOpt.inScaled = true;
        bfOpt.inSampleSize = 2;
        bfOpt.inPurgeable = true;

        bmpThumb = BitmapFactory.decodeStream(bmpBis,null,bfOpt);

        if(bmpThumb == null)
        {
            for(int i=0; i<10; i++)
            {
                Thread.sleep(200);
                System.gc();

                bmpThumb = BitmapFactory.decodeStream(bmpBis,null,bfOpt);


                if(bmpThumb == null)
                    bfOpt.inSampleSize += 1;
                else
                    break;
            }
        }
HttpGet httpRequest = null;
try {
  httpRequest = new HttpGet(url);
} catch (Exception e) {
  e.printStackTrace();
}
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity); 
InputStream instream = bufHttpEntity.getContent();
Bitmap bm = BitmapFactory.decodeStream(instream);