13

現在のアプリケーションでは、スペインのさまざまな「イベント プロバイダー」から画像を収集しています。

  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 接続に問題があるようです。

私の元のコード (上記) はThreadSafeClientConnManagerを利用しています。それを単純なものに置き換えると、URLConnection完全に機能します:

URL url = new URL(strURL);
URLConnection conn = url.openConnection();
conn.connect();
InputStream instream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(instream);

それで、なぜ私のThreadSafeClientConnManager仕事は他のすべての接続(主に交換)では完璧に(少なくともそう見える)、JSONObjects特定のウェブサイトからの画像ではそうではないのか疑問に思っています(例: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 -sometimes-で動作します。画像のダウンロードとデコードを数回連続して試行し続けると、15 ~ 30 回の試行後に機能する可能性があります。非常に奇妙な。

ThreadSafeClientConnManagerの代わりに を使用したいので、解決策があることを願っていURLConnectionます。


更新 3:

以下のMike Mosherが示唆しているように、BufferedHttpEntityを使用することで、デコードエラーは表示されなくなりました。ただし、以前よりも頻度は低くなりましたが、SkImageDecoder::Factory returned nullエラーが発生します。

4

11 に答える 11

27

ステファン、

私は同じ問題を抱えていて、インターネットを検索してもあまり見つかりませんでした。多くの人がこの問題を抱えていますが、それを解決するための答えはあまりありません.

URLConnection を使用して画像を取得していましたが、問題はダウンロードにあるのではなく、BitmapFactory.decodeStream で画像のデコードに問題があることがわかりました。

元のコードを反映するようにコードを変更しました (httpRequest を使用)。http://groups.google.com/group/android-developers/browse_thread/thread/171b8bf35dbbed96/c3ec5f45436ceec8?lnk=raotで見つけた 1 つの変更を加えました(Nilesh に感謝)。「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 枚の画像をダウンロードするページがあり、更新して最新の写真を見ることができます。「デコーダー->デコードが誤ったエラーを返しました」でほぼ半分失敗します。上記のコードでは、問題はありませんでした。

ありがとう

于 2009-12-19T04:14:17.627 に答える
5

私の解決策は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() 関数の場合

private static void copy(InputStream in, OutputStream out) throws IOException {
    byte[] b = new byte[IO_BUFFER_SIZE];
    int read;
    while ((read = in.read(b)) != -1) {
        out.write(b, 0, read);
    }
}

IO_BUFFER_SIZE4 * 1024 の値を持つ整数定数です。

于 2010-01-20T06:55:09.117 に答える
3

これは Android のバグです。あなたのコードは大丈夫です。「Android のデコーダーは現在、デコード時に部分的なデータをサポートしていません。」エンティティに画像がある場合、おそらくそれは部分的な入力ストリームであり、Android は現時点では対応できません。

解決策は、このスレッドから FlushedInputStream を使用することです: http://code.google.com/p/android/issues/detail?id=6066

于 2011-01-13T02:20:47.557 に答える
2
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);
于 2010-11-19T03:03:24.333 に答える
2

このオプションも追加してみてください。

opt.inPurgeable = true;
于 2010-11-02T18:52:35.867 に答える
0

バイト配列から画像をデコードしようとしたときに、まったく同じ問題が発生しました。いくつかの実験の後、解決策は、BitmapFactoryのオプションで一時ストレージを割り当てることであるように見えます。試す:

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

問題がすぐに解決されない場合は、一時配列のサイズを増やしてみてください。大きなビットマップファイルは、デコードするためにより大きなバッファが必要だと思います。

于 2010-02-26T11:07:43.143 に答える
0
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;
            }
        }
于 2010-11-07T22:52:38.293 に答える
0

私は今、ツリーのさまざまな方法を試しました。あなたが使用している単純な URLConnection はあなたのために機能しているようです。Mike Mosher が使用している方法と、この方法も [ http://asantoso.wordpress.com/2008/03/07/download ] -and-view-image-from-the-web/]それらはすべてデコードが false を返します。

ただし、画像をPNGに変換すると、すべての方法が正常に機能します!! しかし、仕事用の ftp ホームページに画像を載せてみたところ、簡単な解決策ですべての jpg が正常に読み込まれました。何らかの理由で、サーバーの速度が十分でない場合、実際に完全にダウンロードされる前に jpg ファイルを解析してしまうようです。か何か。

于 2010-01-06T17:03:25.873 に答える
0

ファイル全体をバッファにダウンロードし、バイト配列をビットマップにデコードしても、このエラー「SkImageDecoder::Factory returned null」が 8 回に 1 回発生します。私は次のことを試しましたが、どれもうまくいきませんでした:

  • http 接続タイプではなく、URL のみを使用する
  • バッファリーダー
  • ファイル全体をダウンロードしてからデコードします

フラッシュされた入力ストリームの回避策もうまくいくとは思いません。Android skia のバグのようです。人々はまだここで問題を報告しています: http://code.google.com/p/android/issues/detail?id=6066 . ビットマップが null の場合に再試行する以外に、このバグの回避策はありません。これは、エラーが発生する可能性を減らすだけです。

于 2011-10-01T19:05:56.113 に答える
0

Options でデフォルト バッファを設定すると、BitmapFactory に関するメモリ不足の問題の一部を解決できますが、すべてをカバーするわけではありません。根本的な問題は、ビットマップまたはビットマップ ヘッダーを取得するときのある種のタイムアウトのようです。現在、ストリームを一時ファイルに書き込み、その一時ファイルを BitmapFactory に渡しています。これは正常に動作しています。

于 2010-09-09T00:14:16.343 に答える