问题
This question is about this popular Android library, Universal Image Loader for Android: https://github.com/nostra13/Android-Universal-Image-Loader
- I made sure WRITE_EXTERNAL_STORAGE is added.
- I enabled both memory and disk cache
- I used UnlimitedDiscCache for disk cache
- 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.
- 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.
回答1:
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();
:)
回答2:
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
回答3:
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
回答4:
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.
来源:https://stackoverflow.com/questions/14305765/filenotfoundexception-with-universal-image-loader