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

Advertisements

25 thoughts on “Android: Web image, photo, picture gallery

  1. Hello,

    I try your code, but it give me this error:

    Caused by: java.lang.NullPointerException at ActivityGallery.java:55

    line 55: g.setAdapter(imageAdapter);

    Can you tell me how we can fix the problem?
    And can you share the source in zip format?

    Thanks you, good work!

  2. Hi vikas..Its really grt to see ur passion over android and the intension to help droidites….cmg to my way….i v added ur source code and included external jars..but still am getting error on

    import org.apache.http.entity.mime.HttpMultipartMode;
    import org.apache.http.entity.mime.MultipartEntity;
    import org.apache.http.entity.mime.content.ByteArrayBody;
    import org.apache.http.entity.mime.content.StringBody;

    plz help me out to resolve dis..may b i v done mistake in adding external jars…

  3. Code shows a warning
    Multiple markers at this line
    – ArrayList is a raw type. References to generic type ArrayList should be
    parameterized
    – ArrayList is a raw type. References to generic type ArrayList should be
    parameterized
    what is the problem?Plz help

  4. hii ,,, your code is really helpful… it helps me a lot… but i m getting a issue…

    my application is crashing after loading two thumbnail images….. so i have done some changes in your code …

    in “private Drawable LoadThumbnailFromURL(String url)” i have used the same code as in “private Drawable LoadImageFromURL(String url)”……………

    Now application is running but still there is issue….

    i have shown the web gallery on one of my five tabs….
    when i go to gallery tab ,, it loads all the images…
    But when i change the tab and get back again to gallery tab….. it again starts loading the images…… from url….

    I have tried everything … but nothing look helpful…
    if you help in this matter ….. i will thankful to you……

    Thnks Vikas for such a nice blog….

    1. Hey thanks for appreciating me, coming to your issue, well actually for couple of weeks, I’m working on BlackBerry Application, so I can’t set up testing environment. I haven’t worked on Android Tab, but you just need to find correct place to put async task call (new AddImageTask().execute();). Here we use on onActivityCreate, so every time activity starts, image downloading will start.

  5. Thnks Vikas, you were right… OnCreate Activity was called everytime………So the images are loading again and again……
    Now it has been solved…….. I m also started to working on blackberry developement……….

    Thnks again vikas for your blog…..

    1. Great!! I am now finishing my BlackBerry App, But this time I use PhoneGap + jquery mobile, so that in future app can also work on windows 7 phone, and may be on Symbian…

  6. The code doesn’t build because of several errors in the code, the ideas seem sound though. Examples include the @lt; in the copied code, a reference to “ImageGallery.this” that should be WebGallery.this, and several other items.

    It would probably be better if you copied from an actual functioning project instead of copying and editing on the fly, more because mostly beginners are probably hitting your blog…

    Thanks for the start though!

    1. Hey thanks for pointing out, and replied. I’m not going to change it because everything is not just copy paste. Users shoud come to what is happening behind the code.

  7. Hi Vikas, I have installed your project, its looks great, many thanks…..

    I do have one problem and hope you can help me. The problem is when i open the app on my phone or emulator it crashes when their is not an internet connection present. Is there a way to overcome this.

    Hope you can help, feel free to email me if you wish

    Lucy

  8. Hi Lucy,

    regarding connection state, you can put this code above on the method that is used to download the pics.

    just before the connection opening.

    ConnectivityManager conMan = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = conMan.getActiveNetworkInfo();
    if(networkInfo.isConnected() == false){
    return null;
    }

    1. Remember that it only checks network connection, not peer to peer connection. You should either use connection timeout and/or socket time out in HTTP class.

      1. HI,
        I have used your code,but while executing thumbnails images are not getting loaded.but when thumbnail is clicked ,the image is been displayed.
        if i replace boolean isImage = contentType.startsWith(“iamge”); with boolean isImage = contentType.startsWith(“http:/”); in LoadThumbnailFromURL(String url) function then all thumbnails are loaded with default image which i have stored in drawable folder.
        Please help me

  9. some NullPointerException is because you dont initialize the imageAdapter…

    put “imageAdapter=new ImageAdapter(getApplicationContext()); ”
    and 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”);

    before gallery_diarios.setAdapter(imageAdapter);

    thanks!!!!

    try the code before publish!!!!!

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s