FileNotFoundException with Universal Image Loader
Asked Answered
P

4

7

This question is about this popular Android library, Universal Image Loader for Android: https://github.com/nostra13/Android-Universal-Image-Loader

  1. I made sure WRITE_EXTERNAL_STORAGE is added.
  2. I enabled both memory and disk cache
  3. I used UnlimitedDiscCache for disk cache
  4. I'm building against Android 2.2 SDK. The exception is found when I'm testing the app on a Android 4.1.2 Nexus S device.
  5. For most of my images, the loading is smooth and fine. However, for certain images, I always get the same exception. Below is an example.

Image URL: http://i10.topit.me/l046/10046137034b1c0db0.jpg

Back trace:

01-14 00:24:42.125: 

ERROR/ImageLoader(1671): http://i10.topit.me/l046/10046137034b1c0db0.jpg

java.io.FileNotFoundException: http://i10.topit.me/l046/10046137034b1c0db0.jpg

at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)

at com.nostra13.universalimageloader.core.download.URLConnectionImageDownloader.getStreamFromNetwork(URLConnectionImageDownloader.java:40)

at com.nostra13.universalimageloader.core.download.ImageDownloader.getStream(ImageDownloader.java:27)

at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.saveImageOnDisc(LoadAndDisplayImageTask.java:296)

at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:204)

at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:128)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)

Please help.

Pincenez answered 13/1, 2013 at 16:54 Comment(4)
Just a wild guess, but those images might need a proxy to be accessed and I remember there were issues with proxies in API level 8.Forsterite
Not likely. All the images are hosted on the same server. Most of them can be downloaded on my testing Android device without a problemPincenez
I get a 404 visiting that page (which would cause file not found), although the 404 page is just an image located at img.topit.me/404.jpg that says (love)it.me.Methylnaphthalene
And now I don't. Use a better image server.Methylnaphthalene
P
12

Follow up:

I finally solved my problem without changing one line of server code. What I did is replacing the default URLConnectionImageDownloader with HttpClientImageDownloader

Code sample:

        HttpParams params = new BasicHttpParams();
        // Turn off stale checking. Our connections break all the time anyway,
        // and it's not worth it to pay the penalty of checking every time.
        HttpConnectionParams.setStaleCheckingEnabled(params, false);
        // Default connection and socket timeout of 10 seconds. Tweak to taste.
        HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
        HttpConnectionParams.setSoTimeout(params, 10 * 1000);
        HttpConnectionParams.setSocketBufferSize(params, 8192);

        // Don't handle redirects -- return them to the caller. Our code
        // often wants to re-POST after a redirect, which we must do ourselves.
        HttpClientParams.setRedirecting(params, false);
        // Set the specified user agent and register standard protocols.
        HttpProtocolParams.setUserAgent(params, "some_randome_user_agent");
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

        ClientConnectionManager manager = new ThreadSafeClientConnManager(params, schemeRegistry);


        ImageLoaderConfiguration config =
                new ImageLoaderConfiguration
                        .Builder(MainActivity.sharedMainActivity.getApplicationContext())
                        .defaultDisplayImageOptions(defaultOptions)
                        .discCache(new UnlimitedDiscCache(cacheDir))
                        .threadPoolSize(1)
                        .memoryCache(new WeakMemoryCache())
                        .imageDownloader(new HttpClientImageDownloader(new DefaultHttpClient(manager, params)))
                        .build();

:)

Pincenez answered 5/2, 2013 at 14:3 Comment(8)
Am I unlucky !!! getting --- SkImageDecoder::Factory returned null, using HttpClientImageDownloaderAdallard
Thanks a lot!! It's helps me. Just one thing in code, need context in last line: .imageDownloader(new HttpClientImageDownloader(msContext, new DefaultHttpClient(manager, params)))Tatty
@DiWu Sorry mate for query im facing same problem. But im using latest version of UIML. In which class you done this changes ? URLConnectionImageDownloader with HttpClientImageDownloader Name of the package and class ?Rajab
03-09 18:12:59.535: E/ImageLoader(9878): java.io.FileNotFoundException: dakabo.dk/images/phocagallery/Levende_vaerksted/dsc09327.jpg%20 03-09 18:12:59.535: E/ImageLoader(9878): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:194) 03-09 18:12:59.535: E/ImageLoader(9878): at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStreamFromNetwork(BaseImageDownloader.java:124)Rajab
Not able to implement this. What is HttpClientImageDownloader class.Pls helpLallans
What is HttpClientImageDownloader class?Iden
I cannot implement this HttpClientImageDownloader, how to make it works?Chickamauga
Nostra removed the class from the library. See: github.com/nostra13/Android-Universal-Image-Loader/commit/…Mealy
B
4

Look for implementation of libcore.net.http.HttpURLConnectionImpl.getInputStream()

 @Override
    public InputStream getInputStream() throws IOException {
        if (!doInput) {
            throw new ProtocolException("This protocol does not support input");
        }

        retrieveResponse();

        /*
         * if the requested file does not exist, throw an exception formerly the
         * Error page from the server was returned if the requested file was
         * text/html this has changed to return FileNotFoundException for all
         * file types
         */
        if (responseCode >= HTTP_BAD_REQUEST) {
            throw new FileNotFoundException(url.toString());
        }

        if (responseBodyIn == null) {
            throw new IOException("No response body exists; responseCode=" + responseCode);
        }

        return responseBodyIn;
    }

According to this it can throw FileNotFoundException even if server error occurs or unauthorized.

I have not found value of HTTP_BAD_REQUEST but it's always was 400. Source code link http://www.java2s.com/Open-Source/Android/android-core/platform-libcore/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java.htm

Bankruptcy answered 13/1, 2013 at 17:2 Comment(4)
And if you go to the address you will find there is such file yourself: i10.topit.me/l046/10046137034b1c0db0.jpgForsterite
Yes, I've just did it. Seems that something strange happens. But stack trace definitely says that file was not foundBankruptcy
Sometimes server really responds 404 (actually it constantly respond 404 after several successful responds). So this is not a UIL's problem.Coprophagous
is there any solution to itAdallard
R
0

The only thing you can do is to disable logging at all by L.disableLogging(). Or change the sources according to your needs. Source: nostra13's answer for this problem

Redoubt answered 5/5, 2016 at 10:0 Comment(0)
S
0

This configuration tuning is custom. You can tune every option, you may tune some of them, or you can create default configuration by ImageLoaderConfiguration.createDefault(this); method.

 public static void initImageLoader(Context context) {

    ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
    config.threadPriority(Thread.NORM_PRIORITY - 2);
    config.denyCacheImageMultipleSizesInMemory();
    config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
    config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
    config.tasksProcessingOrder(QueueProcessingType.LIFO);
    config.writeDebugLogs(); // Remove for release app

    // Initialize ImageLoader with configuration.
    ImageLoader.getInstance().init(config.build());
}

I hope this helps anyone.

Superfluity answered 30/3, 2017 at 16:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.