Tag Archives: Android

Android – Simple XML DOM Parser Example for Reading Response From InputStream


Hi,

I am trying to use simple XML DOM Parser for my HTTP response.

Basically I am calling .Net webservice and I need to parse response.

Let me also cover calling the .Net webservice.

Webservice can be called/consumed by may way.
For Example:

Use SOAP call, HTTP Get method, HTTP Post method and many more..

I have one Web service method with Post call structure:

POST /api.asmx/validateCredentials HTTP/1.1
Host: api.mywebsite.com
Content-Type: application/x-www-form-urlencoded
Content-Length: length

username=string&password=string

Now I want to call it from Android HTTP Post method.
I will also need BasicNameValue pair for sending data to web service URL.

I’ll do it like:

try {
	HttpClient httpClient = new DefaultHttpClient();
	HttpContext localContext = new BasicHttpContext();
	HttpPost httpPost = new HttpPost("http://api.mywebsite.com/api.asmx/validateCredentials");

	List<NameValuePair> nvps = new ArrayList<NameValuePair>();

	nvps.add(new BasicNameValuePair("username", username));
	nvps.add(new BasicNameValuePair("password", password));

	httpPost.setEntity(new UrlEncodedFormEntity(nvps));

	HttpResponse response = httpClient.execute(httpPost, localContext);

} catch (Exception e) {
	e.printStackTrace();
}

Now First of all I wanted my response as String.

So I use Buffer reader to read the data from response object.

BufferedReader reader = new BufferedReader(new InputStreamReader(
		response.getEntity().getContent(), "UTF-8"));
StringBuffer responseString = new StringBuffer("");
String line;
while ((line = reader.readLine()) != null) {
	responseString.append(line);
}
System.out.println(responseString.toString());

Now I can see the response in LogCat.
I get the XML response (in String) as follow:

<?xml version="1.0" encoding="utf-8"?>
<returnMessage xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://api.myserver.com/">
	<responseCode>S000</responseCode>
	<message>User Authenticated</message>
	<extendedMessage>
		The user's credentials were valid and is authorized to execute this transaction.
	</extendedMessage>
	<userno xsi:type="xsd:double">211</userno>
</returnMessage>

Here you can see some tags and actually we need those values!!

So I can now use this “String” object to parse the XML.

To parse the XML we have several methods like SAX parser, DOM parser XML pool parser etc.

I heard that SAX parser is best, I had also used that one, But here I will go with Simple DOM parser.

So Instead of getting the response in String as above, I can directly use InputStream for DOM parser.

InputStream in = response.getEntity().getContent();

DocumentBuilder builder = DocumentBuilderFactory.newInstance()
		.newDocumentBuilder();
Document doc = builder.parse(in);
String responseCode = "";
String extendedMessage = "";
if (doc != null) {
	NodeList nl = doc.getElementsByTagName("responseCode");
	if (nl.getLength() > 0) {
		Node node = nl.item(0);
		responseCode = node.getTextContent();
	}
	nl = doc.getElementsByTagName("extendedMessage");
	if (nl.getLength() > 0) {
		Node node = nl.item(0);
		extendedMessage = node.getTextContent();
	}
}
System.out.println(responseCode + " " + extendedMessage);

I hope this post can help some one who wants to get started with Android in just 10 minutes!

Android Turn screen on, a way of notification


final AlertDialog alert = builder.create();

//Extra screen wake up notification
WindowManager.LayoutParams winParams =  alert.getWindow().getAttributes();
winParams.flags |= (WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
        | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
alert.getWindow().setAttributes(winParams);

alert.show();

Android Focusable EditText inside ListView


Hi,

I was trying to implement something from here. But I don’t understand what he is doing. Using this works well to get focus on EditText.

The main issue I face later, when I have lots of item in ListView. I found this answer very helpful to understand recycling view. You can’t save anything on ListView Item. You must need to handle another data-source that maintain your changes in ListView’s item. Not talking too much, I’m just presenting working example, so readers can understand quickly.

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<ListView android:id="@+id/MyList" android:layout_height="fill_parent"
		android:layout_width="fill_parent" android:descendantFocusability="beforeDescendants">
	</ListView>
</LinearLayout>

item.xml

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

	<EditText android:id="@+id/ItemCaption"
		android:layout_height="wrap_content" android:layout_width="fill_parent"
		android:layout_marginLeft="2dip" android:singleLine="true">
	</EditText>

</LinearLayout>

AndroidCustomListViewActivity.java

package com.isummation.android;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;

public class AndroidCustomListViewActivity extends Activity {
	private ListView myList;
	private MyAdapter myAdapter;

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

		myList = (ListView) findViewById(R.id.MyList);
		myList.setItemsCanFocus(true);
		myAdapter = new MyAdapter();
		myList.setAdapter(myAdapter);

	}

	public class MyAdapter extends BaseAdapter {
		private LayoutInflater mInflater;
		public ArrayList myItems = new ArrayList();

		public MyAdapter() {
			mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			for (int i = 0; i < 20; i++) {
				ListItem listItem = new ListItem();
				listItem.caption = "Caption" + i;
				myItems.add(listItem);
			}
			notifyDataSetChanged();
		}

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

		public Object getItem(int position) {
			return position;
		}

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

		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = mInflater.inflate(R.layout.item, null);
				holder.caption = (EditText) convertView
						.findViewById(R.id.ItemCaption);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}
			//Fill EditText with the value you have in data source
			holder.caption.setText(myItems.get(position).caption);
			holder.caption.setId(position);

			//we need to update adapter once we finish with editing
			holder.caption.setOnFocusChangeListener(new OnFocusChangeListener() {
				public void onFocusChange(View v, boolean hasFocus) {
					if (!hasFocus){
						final int position = v.getId();
						final EditText Caption = (EditText) v;
						myItems.get(position).caption = Caption.getText().toString();
					}
				}
			});

			return convertView;
		}
	}

	class ViewHolder {
		EditText caption;
	}

	class ListItem {
		String caption;
	}
}

Android custom image gallery – part 2 – Add capture button and update gallery


This is the squeal of my previous post to create custom image gallery.

In this post, I added a button to capture new image, and update default gallery.

main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="fill_parent">
	<LinearLayout android:id="@+id/customGalleryFooter"
		android:layout_width="fill_parent" android:layout_height="wrap_content"
		android:orientation="horizontal" android:gravity="center"
		android:layout_alignParentBottom="true">
		<Button android:id="@+id/captureBtn" android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="Capture"
			android:minWidth="200px" />
		<Button android:id="@+id/selectBtn" android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="Select"
			android:minWidth="200px" />
	</LinearLayout>
	<GridView android:id="@+id/PhoneImageGrid"
		android:layout_width="fill_parent" android:layout_height="fill_parent"
		android:numColumns="auto_fit" android:verticalSpacing="10dp"
		android:horizontalSpacing="10dp" android:columnWidth="90dp"
		android:stretchMode="columnWidth" android:gravity="center"
		android:layout_above="@id/customGalleryFooter" />
</RelativeLayout>

AndroidCustomGalleryActivity.java

package com.isummation.customgallery;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

public class AndroidCustomGalleryActivity extends Activity {
	public ImageAdapter imageAdapter;
	private final static int TAKE_IMAGE = 1;
	private Uri imageUri;
	private MediaScannerConnection mScanner;
	public GridView imagegrid;
	private long lastId;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		imageAdapter = new ImageAdapter();
		imageAdapter.initialize();
		imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
		imagegrid.setAdapter(imageAdapter);

		final Button selectBtn = (Button) findViewById(R.id.selectBtn);
		selectBtn.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				final int len = imageAdapter.images.size();
				int cnt = 0;
				String selectImages = "";
				for (int i = 0; i < len; i++) {
					if (imageAdapter.images.get(i).selection) {
						cnt++;
						selectImages = selectImages
								+ imageAdapter.images.get(i).id + ",";
					}
				}
				if (cnt == 0) {
					Toast.makeText(getApplicationContext(),
							"Please select at least one image",
							Toast.LENGTH_LONG).show();
				} else {
					selectImages = selectImages + "-1";
					Intent intent = new Intent(getApplicationContext(),
							UploadQueue.class);
					intent.putExtra("Ids", selectImages);
					startActivityForResult(intent, 2);
				}
				
			}
		});
		final Button captureBtn = (Button) findViewById(R.id.captureBtn);
		captureBtn.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
				String fileName = "IMG_" + sdf.format(new Date()) + ".jpg";
				File myDirectory = new File(Environment
						.getExternalStorageDirectory() + "/REOAllegiance/");
				myDirectory.mkdirs();
				File file = new File(myDirectory, fileName);
				imageUri = Uri.fromFile(file);
				Intent intent = new Intent(
						android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
				intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
				startActivityForResult(intent, TAKE_IMAGE);
			}
		});
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (resultCode) {
		case RESULT_OK:
			try {
				// we need to update the gallery by starting MediaSanner service.
				mScanner = new MediaScannerConnection(
						AndroidCustomGalleryActivity.this,
						new MediaScannerConnection.MediaScannerConnectionClient() {
							public void onMediaScannerConnected() {
								mScanner.scanFile(imageUri.getPath(), null /* mimeType */);
							}

							public void onScanCompleted(String path, Uri uri) {
								//we can use the uri, to get the newly added image, but it will return path to full sized image
								//e.g. content://media/external/images/media/7
								//we can also update this path by replacing media by thumbnail to get the thumbnail
								//because thumbnail path would be like content://media/external/images/thumbnail/7
								//But the thumbnail is created after some delay by Android OS
								//So you may not get the thumbnail. This is why I started new UI thread
								//and it'll only run after the current thread completed.
								if (path.equals(imageUri.getPath())) {
									mScanner.disconnect();
									//we need to create new UI thread because, we can't update our mail thread from here
									//Both the thread will run one by one, see documentation of android  
									AndroidCustomGalleryActivity.this
											.runOnUiThread(new Runnable() {
												public void run() {
													updateUI();
												}
											});
								}
							}
						});
				mScanner.connect();

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void updateUI() {
		imageAdapter.checkForNewImages();
	}

	public class ImageAdapter extends BaseAdapter {
		private LayoutInflater mInflater;
		public ArrayList<ImageItem> images = new ArrayList<ImageItem>();

		public ImageAdapter() {
			mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}

		public void initialize() {
			images.clear();
			final String[] columns = { MediaStore.Images.Thumbnails._ID };
			final String orderBy = MediaStore.Images.Media._ID;
			Cursor imagecursor = managedQuery(
					MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
					null, null, orderBy);
			int image_column_index = imagecursor
					.getColumnIndex(MediaStore.Images.Media._ID);
			int count = imagecursor.getCount();
			for (int i = 0; i < count; i++) {
				imagecursor.moveToPosition(i);
				int id = imagecursor.getInt(image_column_index);
				ImageItem imageItem = new ImageItem();
				imageItem.id = id;
				lastId = id;
				Log.d("l_id", ""+ id);
				imageItem.img = MediaStore.Images.Thumbnails.getThumbnail(
						getApplicationContext().getContentResolver(), id,
						MediaStore.Images.Thumbnails.MICRO_KIND, null);
				images.add(imageItem);
			}
			imagecursor.close();
			notifyDataSetChanged();
		}
		
		public void checkForNewImages(){
			//Here we'll only check for newer images
			final String[] columns = { MediaStore.Images.Thumbnails._ID };
			final String orderBy = MediaStore.Images.Media._ID;
			Cursor imagecursor = managedQuery(
					MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
					MediaStore.Images.Media._ID + " > " + lastId , null, orderBy);
			int image_column_index = imagecursor
					.getColumnIndex(MediaStore.Images.Media._ID);
			int count = imagecursor.getCount();
			for (int i = 0; i < count; i++) {
				imagecursor.moveToPosition(i);
				int id = imagecursor.getInt(image_column_index);
				ImageItem imageItem = new ImageItem();
				imageItem.id = id;
				lastId = id;
				imageItem.img = MediaStore.Images.Thumbnails.getThumbnail(
						getApplicationContext().getContentResolver(), id,
						MediaStore.Images.Thumbnails.MICRO_KIND, null);
				imageItem.selection = true; //newly added item will be selected by default
				images.add(imageItem);
			}
			imagecursor.close();
			notifyDataSetChanged();
		}

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

		public Object getItem(int position) {
			return position;
		}

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

		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = mInflater.inflate(R.layout.galleryitem, null);
				holder.imageview = (ImageView) convertView
						.findViewById(R.id.thumbImage);
				holder.checkbox = (CheckBox) convertView
						.findViewById(R.id.itemCheckBox);

				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}
			ImageItem item = images.get(position);
			holder.checkbox.setId(item.id);
			holder.imageview.setId(item.id);
			holder.checkbox.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					// TODO Auto-generated method stub
					CheckBox cb = (CheckBox) v;
					int id = cb.getId();
					if (images.get(id).selection) {
						cb.setChecked(false);
						images.get(id).selection = false;
					} else {
						cb.setChecked(true);
						images.get(id).selection = true;
					}
				}
			});
			holder.imageview.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					// TODO Auto-generated method stub
					int id = v.getId();
					Intent intent = new Intent();
					intent.setAction(Intent.ACTION_VIEW);
					final String[] columns = { MediaStore.Images.Media.DATA };
					Cursor imagecursor = managedQuery(
							MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
							MediaStore.Images.Media._ID + " = " + id, null, MediaStore.Images.Media._ID);
					if (imagecursor != null && imagecursor.getCount() > 0){
						imagecursor.moveToPosition(0);
						String path = imagecursor.getString(imagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
						imagecursor.close();
						intent.setDataAndType(
								Uri.parse("file://" + path),
								"image/*");
						startActivityForResult(intent, 3);
					}
				}
			});
			holder.imageview.setImageBitmap(item.img);
			holder.checkbox.setChecked(item.selection);
			return convertView;
		}
	}

	class ViewHolder {
		ImageView imageview;
		CheckBox checkbox;
	}

	class ImageItem {
		boolean selection;
		int id;
		Bitmap img;
	}
	
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
	}
}

Update:
I highly recommend to do not use this code, as it is old and with some bugs. Please visit my open source project page, Where I keep updating code.

Android custom image gallery with checkbox in grid to select multiple


Some times we may require to select multiple images from gallery. So using the following method you will be able to select multiple images. Additionally it will also remove gallery app dependency.

It may not be sufficient method as I need to maintain two array in this activity, but it could vary on requirements. Please comment if you have any suggestion in code.

Main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="fill_parent">
	<Button android:id="@+id/selectBtn"
		android:layout_width="wrap_content" android:layout_height="wrap_content"
		android:text="Select" android:layout_alignParentBottom="true"
		android:layout_centerHorizontal="true"
		android:minWidth="200px" />
	<GridView android:id="@+id/PhoneImageGrid"
		android:layout_width="fill_parent" android:layout_height="fill_parent"
		android:numColumns="auto_fit" android:verticalSpacing="10dp"
		android:horizontalSpacing="10dp" android:columnWidth="90dp"
		android:stretchMode="columnWidth" android:gravity="center"
		android:layout_above="@id/selectBtn" />
</RelativeLayout>

galleryitem.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="fill_parent">
	<ImageView android:id="@+id/thumbImage" android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:layout_centerInParent="true" />
	<CheckBox android:id="@+id/itemCheckBox" android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:layout_alignParentRight="true"
		android:layout_alignParentTop="true" />
</RelativeLayout>

AndroidCustomGalleryActivity.java

package com.isummation.customgallery;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

public class AndroidCustomGalleryActivity extends Activity {
	private int count;
	private Bitmap[] thumbnails;
	private boolean[] thumbnailsselection;
	private String[] arrPath;
	private ImageAdapter imageAdapter;

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

		final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
		final String orderBy = MediaStore.Images.Media._ID;
		Cursor imagecursor = managedQuery(
				MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,
				null, orderBy);
		int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
		this.count = imagecursor.getCount();
		this.thumbnails = new Bitmap[this.count];
		this.arrPath = new String[this.count];
		this.thumbnailsselection = new boolean[this.count];
		for (int i = 0; i < this.count; i++) {
			imagecursor.moveToPosition(i);
			int id = imagecursor.getInt(image_column_index);
			int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
			thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail(
					getApplicationContext().getContentResolver(), id,
					MediaStore.Images.Thumbnails.MICRO_KIND, null);
			arrPath[i]= imagecursor.getString(dataColumnIndex);
		}
		GridView imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
		imageAdapter = new ImageAdapter();
		imagegrid.setAdapter(imageAdapter);
		imagecursor.close();

		final Button selectBtn = (Button) findViewById(R.id.selectBtn);
		selectBtn.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				// TODO Auto-generated method stub
				final int len = thumbnailsselection.length;
				int cnt = 0;
				String selectImages = "";
				for (int i =0; i<len; i++)
				{
					if (thumbnailsselection[i]){
						cnt++;
						selectImages = selectImages + arrPath[i] + "|";
					}
				}
				if (cnt == 0){
					Toast.makeText(getApplicationContext(),
							"Please select at least one image",
							Toast.LENGTH_LONG).show();
				} else {
					Toast.makeText(getApplicationContext(),
							"You've selected Total " + cnt + " image(s).",
							Toast.LENGTH_LONG).show();
					Log.d("SelectedImages", selectImages);
				}
			}
		});
	}

	public class ImageAdapter extends BaseAdapter {
		private LayoutInflater mInflater;

		public ImageAdapter() {
			mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}

		public int getCount() {
			return count;
		}

		public Object getItem(int position) {
			return position;
		}

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

		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = mInflater.inflate(
						R.layout.galleryitem, null);
				holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
				holder.checkbox = (CheckBox) convertView.findViewById(R.id.itemCheckBox);

				convertView.setTag(holder);
			}
			else {
				holder = (ViewHolder) convertView.getTag();
			}
			holder.checkbox.setId(position);
			holder.imageview.setId(position);
			holder.checkbox.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					// TODO Auto-generated method stub
					CheckBox cb = (CheckBox) v;
					int id = cb.getId();
					if (thumbnailsselection[id]){
						cb.setChecked(false);
						thumbnailsselection[id] = false;
					} else {
						cb.setChecked(true);
						thumbnailsselection[id] = true;
					}
				}
			});
			holder.imageview.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					// TODO Auto-generated method stub
					int id = v.getId();
					Intent intent = new Intent();
					intent.setAction(Intent.ACTION_VIEW);
					intent.setDataAndType(Uri.parse("file://" + arrPath[id]), "image/*");
					startActivity(intent);
				}
			});
			holder.imageview.setImageBitmap(thumbnails[position]);
			holder.checkbox.setChecked(thumbnailsselection[position]);
			holder.id = position;
			return convertView;
		}
	}
	class ViewHolder {
		ImageView imageview;
		CheckBox checkbox;
		int id;
	}
}

Download full source code:
Download

Update: need more features? see my open source project
Update: Please remove code that closes cursor. As this will not work in Android 4.0 and newer.

https://vikaskanani.wordpress.com/android-custom-gallery-and-instant-upload-project/