What is the simplest way to fetch an image from a url in an android program?
You do it many ways but the simplist way I can think of would be something like this:
Bitmap IMG;
Thread t = new Thread(){
public void run(){
try {
/* Open a new URL and get the InputStream to load data from it. */
URL aURL = new URL("YOUR URL");
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
/* Buffered is always good for a performance plus. */
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
IMG = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
// ...send message to handler to populate view.
mHandler.sendEmptyMessage(0);
} catch (Exception e) {
Log.e(DEB, "Remtoe Image Exception", e);
mHandler.sendEmptyMessage(1);
} finally {
}
}
};
t.start();
And then add a handler to your code:
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
switch(msg.what){
case 0:
(YOUR IMAGE VIEW).setImageBitmap(IMG);
break;
case 1:
onFail();
break;
}
}
};
By starting a thread and adding a handler you are able to load the images without locking up the UI during download.
I would strongly recommend using an AsyncTask instead. I originally used URL.openStream, but it has issues.
class DownloadThread extends AsyncTask<URL,Integer,List<Bitmap>>{
protected List<Bitmap> doInBackground(URL... urls){
InputStream rawIn=null;
BufferedInputStream bufIn=null;
HttpURLConnection conn=null;
try{
List<Bitmap> out=new ArrayList<Bitmap>();
for(int i=0;i<urls.length;i++){
URL url=urls[i];
url = new URL("http://mysite/myimage.png");
conn=(HttpURLConnection) url.openConnection()
if(!String.valueOf(conn.getResponseCode()).startsWith('2'))
throw new IOException("Incorrect response code "+conn.getResponseCode()+" Message: " +getResponseMessage());
rawIn=conn.getInputStream();
bufIn=new BufferedInputStream();
Bitmap b=BitmapFactory.decodeStream(in);
out.add(b);
publishProgress(i);//Remove this line if you don't want to use AsyncTask
}
return out;
}catch(IOException e){
Log.w("networking","Downloading image failed");//Log is an Android specific class
return null;
}
finally{
try {
if(rawIn!=null)rawIn.close();
if(bufIn!=null)bufIn.close();
if(conn!=null)conn.disconnect();
}catch (IOException e) {
Log.w("networking","Closing stream failed");
}
}
}
}
Closing the stream/connection and exception handling is difficult in this case. According to Sun Documentation you should only need to close the outermost stream, however it appears to be more complicated. However, I am closing the inner most stream first to ensure it is closed if we can't close the BufferedInputStream
.
We close in a finally so that an exception doesn't prevent them being closed. We account for the possibility of the streams will being null
if an exception prevented them from being initialised. If we have an exception during closing, we simply log and ignore this. Even this might not work properly if a runtime error occurs .
You can use the AsyncTask
class as follows. Start an animation in onPreExecute
. Update the progress in onProgressUpdate
. onPostExecute
should handle the actual images. Use onCancel
to allow the user to cancel the operation. Start it with AsyncTask.execute
.
It is worth noting that the source code and the license allow us to use the class in non-Android projects.