In this article we will create an Android application to display the thumbnails of SDCard images in a listview. The details of the images such as title, size, width and height are also be displayed in the listview.
The thumbnails of the images can be retrieved using the content provider android.provider.MediaStore.Images.Thumbnails.
The details of the images can be retrieved using the content provider android.provider.MediaStore.Images.Media.
We are using a loader identified by the unique id THUMBNAIL_LOADER_ID to load thumbnail images to the cursor variable mThumbCursor.
We are using a loader identified by the unique id IMAGE_LOADER_ID to load thumbnail images to the cursor mImageCursor.
The cursors mThumbCursor and mImageCursor will be merged to a MatrixCursor variable mMatrixCursor. This MatrixCursor will be set to listview as its adapter to display the images and its details in the listview.
This application is developed in Eclipse ( 4.2.0 ) with ADT plugin ( 20.0.3 ) and Android SDK ( R20.0.3 ).
1. Create a new Android application project namely “ListViewWithSDCardImages”
2. Design an application launcher icon
3. Create a blank activity to define the MainActivity class
4. Enter MainActivity class details
5. Add Android’s Support Library to this project
Loaders are introduced in Android API level 11 ( Honeycomb ) but can be used in pre Honeycomb versions using Android’s support library. Since this application will run in API level 4 and above, we need to add Android Support library to this project to use Loaders in our application.
By default, Android support library (android-support-v4.jar ) is added to this project by Eclipse IDE to the directory libs. If it is not added, we can do it manually by doing the following steps :
- Open Project Explorer by Clicking “Window -> Show View -> Project Explorer”
- Right click this project
- Then from popup window, Click “Android Tools -> Add Support Library “
6. Update the file res/values/strings.xml
<resources> <string name="app_name">ListViewWithSDCardImages</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string name="title_activity_main">ListView with Images</string> </resources>
7. Update the layout of the MainActivity in the file res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/lv_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:context=".MainActivity" /> </RelativeLayout>
8. Create a new layout for the listview items in the file res/layout/lv_layout.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="75dp" > <ImageView android:id="@+id/img_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content"integrate android:layout_alignParentLeft="true" android:adjustViewBounds="true" android:padding="5dp" /> <TextView android:id="@+id/tv_details" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/img_thumbnail" android:padding="5dp" /> </RelativeLayout>
9. Update the class MainActivity in the file src/in/wptrafficanalyzer/listviewwithsdcardimages/MainActivity.java
package in.wptrafficanalyzer.listviewwithsdcardimages; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.SimpleCursorAdapter; import android.view.Menu; import android.widget.ListView; public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> { SimpleCursorAdapter mAdapter; private final int THUMBNAIL_LOADER_ID = 0; private final int IMAGE_LOADER_ID = 1; MatrixCursor mMatrixCursor; Cursor mThumbCursor; Cursor mImageCursor; String mThumbImageId=""; String mThumbImageData=""; String mImageSize=""; String mImageTitle=""; String mImageWidth=""; String mImageHeight=""; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** Initializing MatrixCursor */ mMatrixCursor = new MatrixCursor(new String[]{"_id","_data","_details"}); /** Getting a reference to listview of the MainActivity layout */ ListView lVThumbnail = (ListView) findViewById(R.id.lv_thumbnail); /** Creating an adapter object to set image and text in the listview */ mAdapter = new SimpleCursorAdapter( getBaseContext(), R.layout.lv_layout, null, new String[] { "_data","_details"} , new int[] { R.id.img_thumbnail,R.id.tv_details}, 0 ); /** Setting adapter for the listview */ lVThumbnail.setAdapter(mAdapter); /** Loader to get thumbnail images from the SD Card */ getSupportLoaderManager().initLoader(THUMBNAIL_LOADER_ID, null, this); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } /** A callback method invoked by the loader when initLoader() is called */ @Override public Loader<Cursor> onCreateLoader(int loader_id, Bundle arg1) { CursorLoader cLoader; Uri uri; if(loader_id==THUMBNAIL_LOADER_ID){ /** Querying Thumbnail content provider */ uri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI; cLoader = new CursorLoader(this, uri, null, null, null, null); }else { /** Querying Image Content provider with thumbnail image id */ String image_id = arg1.getString("image_id"); uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; cLoader = new CursorLoader(this, uri, null, MediaStore.Images.Media._ID +"=" +image_id, null, null); } return cLoader; } /** A callback method, invoked after the requested content provider returned all the data */ @Override public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) { if(arg0.getId()==THUMBNAIL_LOADER_ID){ /** Thumbnail cursor is loaded completely */ mThumbCursor = arg1; if(mThumbCursor.moveToFirst()){ /** Taking the first thumbnail */ mThumbImageId = mThumbCursor.getString(mThumbCursor.getColumnIndex(MediaStore.Images.Thumbnails._ID)); mThumbImageData = mThumbCursor.getString(mThumbCursor.getColumnIndex(MediaStore.Images.Thumbnails.DATA)); /** Getting the image id from the mThumbCursor and putting in to the bundle*/ String image_id = mThumbCursor.getString(mThumbCursor.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID)); Bundle data = new Bundle(); data.putString("image_id", image_id); /** Intiates the Image Loader onCreateLoader() */ getSupportLoaderManager().initLoader(IMAGE_LOADER_ID, data, this); } }else if(arg0.getId() == IMAGE_LOADER_ID){ mImageCursor = arg1; if(mImageCursor.moveToFirst()){ mImageTitle = mImageCursor.getString(mImageCursor.getColumnIndex(MediaStore.Images.Media.TITLE)); mImageSize = mImageCursor.getString(mImageCursor.getColumnIndex(MediaStore.Images.Media.SIZE)); mImageWidth = mThumbCursor.getString(mThumbCursor.getColumnIndex(MediaStore.Images.Thumbnails.WIDTH)); mImageHeight = mThumbCursor.getString(mThumbCursor.getColumnIndex(MediaStore.Images.Thumbnails.HEIGHT)); String details = "Title:"+mImageTitle + "\n" + "Size:" + mImageSize + " Bytes " + "\n" + "Resolution:" + mImageWidth + " x " + mImageHeight ; /** Adding new row to the matrixcursor object */ mMatrixCursor.addRow(new Object[]{ mThumbImageId,mThumbImageData, details }); /** Taking the next thumbnail */ if(mThumbCursor.moveToNext()){ mThumbImageId = mThumbCursor.getString(mThumbCursor.getColumnIndex(MediaStore.Images.Thumbnails._ID)); mThumbImageData = mThumbCursor.getString(mThumbCursor.getColumnIndex(MediaStore.Images.Thumbnails.DATA)); String image_id = mThumbCursor.getString(mThumbCursor.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID)); Bundle data = new Bundle(); data.putString("image_id", image_id); /** Restarting the image loader to get the next image details */ getSupportLoaderManager().restartLoader(IMAGE_LOADER_ID, data, this); }else{ /** No more thumbnails exists */ if(mThumbCursor.isAfterLast()) mAdapter.swapCursor(mMatrixCursor); /** Set the thumbnails and its details in the listview */ } } } } @Override public void onLoaderReset(Loader<Cursor> arg0) { // TODO Auto-generated method stub } }
10. Screenshot of the application in execution
11. Download

12. Reference
http://developer.android.com/guide/index.html

I am George Mathew, working as software architect and Android app developer at wptrafficanalyzer.in
You can hire me on hourly basis or on project basis for Android applications development.
For hiring me, please mail your requirements to info@wptrafficanalyzer.in.
My other blogs
store4js.blogspot.com
Thank you George Mathew, for posting the code here. But, when I run this application, I am getting blank activity. Why?
once i write permission in AndroidManifest.xml….its perfectly working
Thanks a Ton .
Thank you George Mathew
Can you please tell me how can we get a particular folder images instead of all the images from SD card..Thans in Advance
how to show main folders of SD card and Internal memory in list view
and set click event on it?
Thank you for this tutorial. What is getSupportLoaderManager() ?
Hi,
what is the maximum size of image we can show in listview through this code?
thanks
I tried the code but it never goes in this else block
else{ /** No more thumbnails exists */
if(mThumbCursor.isAfterLast())
mAdapter.swapCursor(mMatrixCursor); /** Set the thumbnails and its details in the listview */
}
am doing an application where the user loads the image from the memory card and itemclick by a different user ,the user is given the options comment,like and buy.How can I get to achieve this