Android: Web image, photo, picture gallery


Hi.

Recently I’ve created web image gallery for my application. That took much of the time when I test it under various condition. Each time I need to improve my code. So that finally I decided to post my work.

It is easy to show images from phone, but to display images from web (or from url), you need to take care of downloading images to your application, image size, image exist or not etc..

Consider that your server contains two type of images, one is original and second is thumbnail.

e.g.

Thumbnail: th_3BC52DAA-AFD8-50B5-DA5096B82422275F.jpg

Original: 3BC52DAA-AFD8-50B5-DA5096B82422275F.jpg

All the images are in /upload directory.

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="fill_parent"	android:orientation="vertical">
	<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
		android:id="@+id/Gallery" android:layout_width="fill_parent"
		android:layout_height="wrap_content" />
	<ImageView android:id="@+id/GalleryView"
		android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>

MyGallery.java

package com.isummation.igallery;

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Toast;
public class MyGallery extends Activity {

	private ImageAdapter imageAdapter;

	private ArrayList PhotoURLS = new ArrayList();
	private ProgressDialog dialog;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		imageAdapter = new ImageAdapter(this);
		final ImageView imgView = (ImageView) findViewById(R.id.GalleryView);
		Gallery g = (Gallery) findViewById(R.id.Gallery);
		g.setAdapter(imageAdapter);
		g.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView parent, View v,
					int position, long id) {
				dialog = ProgressDialog.show(ImageGallery.this, "Loading",
						"Please wait...", true);
				new ShowImageTask().execute(position);
			}
		});

		// replace this code to set your image urls in list
		PhotoURLS.add("http://10.0.2.2/upload/3BC52DAA-AFD8-50B5-DA5096B82422275F.jpg");
		PhotoURLS.add("http://10.0.2.2/upload/B652F78D-C760-B674-7A6E61E505A05A0F.jpg");

		new AddImageTask().execute();

	}

	class ShowImageTask extends AsyncTask {
		@Override
		protected Drawable doInBackground(Integer... position) {
			Drawable drawable = LoadImageFromURL(PhotoURLS.get(position[0]));
			return drawable;
		}

		@Override
		protected void onProgressUpdate(Void... unsued) {

		}

		@Override
		protected void onPostExecute(Drawable drawable) {
			imgView.setImageDrawable(drawable);
			imgView.setScaleType(ImageView.ScaleType.FIT_CENTER);
			dialog.dismiss();
		}
	}

	class AddImageTask extends AsyncTask<Void, Void, Void> {
		@Override
		protected Void doInBackground(Void... unused) {
			for (String url : PhotoURLS) {
				String filename = url.substring(url.lastIndexOf("/") + 1,
						url.length());
				filename = "th_" + filename;
				String thumburl = url.substring(0, url.lastIndexOf("/") + 1);
				imageAdapter.addItem(LoadThumbnailFromURL(thumburl + filename));
				publishProgress();
				//SystemClock.sleep(200);
			}

			return (null);
		}

		@Override
		protected void onProgressUpdate(Void... unused) {
			imageAdapter.notifyDataSetChanged();
		}

		@Override
		protected void onPostExecute(Void unused) {
		}
	}

	private Drawable LoadThumbnailFromURL(String url) {
		try {
			URLConnection connection = new URL(url).openConnection();
			String contentType = connection.getHeaderField("Content-Type");
			boolean isImage = contentType.startsWith("image/");
			if(isImage){
				HttpGet httpRequest = new HttpGet(url);
				HttpClient httpclient = new DefaultHttpClient();
				HttpResponse response = (HttpResponse) httpclient
						.execute(httpRequest);
				HttpEntity entity = response.getEntity();
				BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);

				InputStream is = bufferedHttpEntity.getContent();
				Drawable d = Drawable.createFromStream(is, "src Name");
				return d;
			} else {
				Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.no_image);
				Drawable d = new BitmapDrawable(b);
				return d;
			}
		} catch (Exception e) {
			Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_LONG)
					.show();
			Log.e(e.getClass().getName(), e.getMessage(), e);
			return null;
		}
	}

	private Drawable LoadImageFromURL(String url) {
		try {
			URLConnection connection = new URL(url).openConnection();
			String contentType = connection.getHeaderField("Content-Type");
			boolean isImage = contentType.startsWith("image/");
			if(isImage){
				HttpGet httpRequest = new HttpGet(url);
				HttpClient httpclient = new DefaultHttpClient();
				HttpResponse response = (HttpResponse) httpclient
						.execute(httpRequest);
				HttpEntity entity = response.getEntity();
				BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(
						entity);
				InputStream is = bufferedHttpEntity.getContent();

				// Decode image size
				BitmapFactory.Options o = new BitmapFactory.Options();
				o.inJustDecodeBounds = true;
				BitmapFactory.decodeStream(is, null, o);

				// The new size we want to scale to
				final int REQUIRED_SIZE = 150;

				// Find the correct scale value. It should be the power of 2.
				int width_tmp = o.outWidth, height_tmp = o.outHeight;
				int scale = 1;
				while (true) {
					if (width_tmp / 2 &lt; REQUIRED_SIZE
							|| height_tmp / 2 &lt; REQUIRED_SIZE)
						break;
					width_tmp /= 2;
					height_tmp /= 2;
					scale *= 2;
				}

				// Decode with inSampleSize
				is = bufferedHttpEntity.getContent();
				BitmapFactory.Options o2 = new BitmapFactory.Options();
				o2.inSampleSize = scale;
				Bitmap b = BitmapFactory.decodeStream(is, null, o2);
				Drawable d = new BitmapDrawable(b);
				return d;
			} else {
				Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.no_image);
				Drawable d = new BitmapDrawable(b);
				return d;
			}
		} catch (Exception e) {
			Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_LONG)
					.show();
			Log.e(e.getClass().getName(), e.getMessage(), e);
			return null;
		}
	}

	public class ImageAdapter extends BaseAdapter {
		int mGalleryItemBackground;
		private Context mContext;

		ArrayList drawablesFromUrl = new ArrayList();

		public ImageAdapter(Context c) {
			mContext = c;
			TypedArray a = obtainStyledAttributes(R.styleable.GalleryTheme);
			mGalleryItemBackground = a.getResourceId(
					R.styleable.GalleryTheme_android_galleryItemBackground, 0);
			a.recycle();
		}

		public void addItem(Drawable item) {
			drawablesFromUrl.add(item);
		}

		public int getCount() {
			return drawablesFromUrl.size();
		}

		public Drawable getItem(int position) {
			return drawablesFromUrl.get(position);
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			ImageView i = new ImageView(mContext);

			i.setImageDrawable(drawablesFromUrl.get(position));
			i.setLayoutParams(new Gallery.LayoutParams(80, 70));
			i.setScaleType(ImageView.ScaleType.FIT_CENTER);
			i.setBackgroundResource(mGalleryItemBackground);

			return i;
		}
	}

}

Also /res/values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="GalleryTheme">
        <attr name="android:galleryItemBackground" />
    </declare-styleable>
</resources>

Dont forget to add permission in AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>

Also add this image to Drawable:

Note: Some code is taken from Stackoverflow.com and Androidpeople.com

Update:

Download source code: Download