问题
I have this code to load an image. The server is secured. I got a response: 200 which means okay. Then also the right url is to be loaded. The problem is when i run my app, the image wont be loaded.
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
String userPass = username+":"+password;
String encode = Base64.encodeToString(userPass.getBytes(), Base64.DEFAULT);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setRequestProperty("Authorization", "Basic " + encode);
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setInstanceFollowRedirects(true);
int res = conn.getResponseCode();
System.out.println("Response: " + res);
System.out.println("Image Loader URL: " + url);
InputStream is=conn.getInputStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex){
ex.printStackTrace();
if(ex instanceof OutOfMemoryError)
memoryCache.clear();
return null;
}
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=360;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
Log.d("IMAGE SIZE? ", +width_tmp+ " x " + height_tmp);
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
/// . . . . . and so on...\
In my logcat..one time it should SKImageDecoder::Factory returned null
But then, maybe i did something..this now what i see in my logcat..
04-17 16:18:57.936: D/libEGL(5216): loaded /system/lib/egl/libGLES_android.so
04-17 16:18:57.940: D/libEGL(5216): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
04-17 16:18:57.952: D/libEGL(5216): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
04-17 16:18:57.955: D/libEGL(5216): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
04-17 16:18:58.087: D/OpenGLRenderer(5216): Enabling debug mode 0
I guess my image was decoded since i logged IMAGE SIZE?
: then it logged the right image size of the image i want to load.
Is the problem on the ImageLoader or the rendering part?
Any insights please. Thanks.
回答1:
try with this class, it download the image in background and store in cache:
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
/**
* This Class is for download images and assign the drawable to an ImageView.
*
*/
public class DrawableBackgroundDownloader {
private final Map<String, Drawable> mCache = new HashMap<String, Drawable>();
private final LinkedList <Drawable> mChacheController = new LinkedList <Drawable> ();
private ExecutorService mThreadPool;
private final Map<ImageView, String> mImageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
public static int MAX_CACHE_SIZE = 80;
public int THREAD_POOL_SIZE = 3;
/**
* Constructor
*/
public DrawableBackgroundDownloader() {
mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
}
/**
* Clears all instance data and stops running threads
*/
public void Reset() {
ExecutorService oldThreadPool = mThreadPool;
mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
oldThreadPool.shutdownNow();
mChacheController.clear();
mCache.clear();
mImageViews.clear();
}
/**
* Load the drawable associated to a url and assign it to an image, you can set a placeholder to replace this drawable.
* @param url Is the url of the image.
* @param imageView The image to assign the drawable.
* @param placeholder A drawable that is show during the image is downloading.
*/
public void loadDrawable(final String url, final ImageView imageView,Drawable placeholder) {
if(!mImageViews.containsKey(url))
mImageViews.put(imageView, url);
Drawable drawable = getDrawableFromCache(url);
// check in UI thread, so no concurrency issues
if (drawable != null) {
//Log.d(null, "Item loaded from mCache: " + url);
imageView.setImageDrawable(drawable);
} else {
imageView.setImageDrawable(placeholder);
queueJob(url, imageView, placeholder);
}
}
/**
* Return a drawable from the cache.
* @param url url of the image.
* @return a Drawable in case that the image exist in the cache, else returns null.
*/
public Drawable getDrawableFromCache(String url) {
if (mCache.containsKey(url)) {
return mCache.get(url);
}
return null;
}
/**
* Save the image to cache memory.
* @param url The image url
* @param drawable The drawable to save.
*/
private synchronized void putDrawableInCache(String url,Drawable drawable) {
int chacheControllerSize = mChacheController.size();
if (chacheControllerSize > MAX_CACHE_SIZE)
mChacheController.subList(0, MAX_CACHE_SIZE/2).clear();
mChacheController.addLast(drawable);
mCache.put(url, drawable);
}
/**
* Queue the job to download the image.
* @param url Image url.
* @param imageView The ImageView where is assigned the drawable.
* @param placeholder The drawable that is show during the image is downloading.
*/
private void queueJob(final String url, final ImageView imageView,final Drawable placeholder) {
/* Create handler in UI thread. */
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
String tag = mImageViews.get(imageView);
if (tag != null && tag.equals(url)) {
if (imageView.isShown())
if (msg.obj != null) {
imageView.setImageDrawable((Drawable) msg.obj);
} else {
imageView.setImageDrawable(placeholder);
//Log.d(null, "fail " + url);
}
}
}
};
mThreadPool.submit(new Runnable() {
public void run() {
final Drawable bmp = downloadDrawable(url);
// if the view is not visible anymore, the image will be ready for next time in cache
if (imageView.isShown())
{
Message message = Message.obtain();
message.obj = bmp;
//Log.d(null, "Item downloaded: " + url);
handler.sendMessage(message);
}
}
});
}
/**
* Method that download the image
* @param url The url image.
* @return Returns the drawable associated to this image.
*/
private Drawable downloadDrawable(String url) {
try {
InputStream is = getInputStream(url);
Drawable drawable = Drawable.createFromStream(is, url);
putDrawableInCache(url,drawable);
return drawable;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* This method manage the connection to download the image.
* @param urlString url of the image.
* @return Returns an InputStream associated with the url image.
* @throws MalformedURLException
* @throws IOException
*/
private InputStream getInputStream(String urlString) throws MalformedURLException, IOException {
URL url = new URL(urlString);
URLConnection connection;
connection = url.openConnection();
connection.setUseCaches(true);
connection.connect();
InputStream response = connection.getInputStream();
return response;
}
}
is easy to use just declare:
DrawableBackgroundDownloader drawableDownloader = new DrawableBackgroundDownloader();
and where do you want to use:
drawableDownloader.loadDrawable(String urlImage, ImageView iView,Drawable drawable);
where drawable is a Drawable that is showing during image download.
来源:https://stackoverflow.com/questions/16055375/android-loading-image-url-and-displaying-in-imageview