How to create Image Gallery App using MediaStore in Android

In the last tutorial, we have learned about how to create Video Gallery app in android. In this tutorial, we are going to create an Image Gallery App for Android.We can also add pinch zoom, crop, resize, delete and other functionality as well but we do not discuss these function in this tutorial because it will make the development complex and hard to understand.

 Create Project For Image Gallery

First of all, create a project with the name of Image Gallery and choose default empty activity. Once your project will be created it will look like as given below.
Image Gallery Project Structure
Image Gallery App Project Structure

So our project gets created with default man activity and layout file, now we have to work further to add the functionality to our Image Gallery App so that it can show the all image from user sd card.

 You may like this:

Add RecylerView to activity_main.xml

So here we are going to add a Recycler view to our main layout file which contains all Photo of our SD card. But before adding the Recycler view we have to add the library in our app level gardle file.
So add below line at the app level build.gradle file.
compile 'com.android.support:recyclerview-v7:24.2.0'
we also required a card view for our item inside recycler view so we need to add other dependencies in our Gradle file.
compile 'com.android.support:cardview-v7:24.2.0'
The last dependency we are adding here is glide library which we are going to use to retrieve our thumbnail from the photo and showing it in the image view. So add the below library also in our app level build.gardle file.
compile 'com.github.bumptech.glide:glide:3.7.0'
So after adding the dependency to our build.gardle file it will look like as given below.
 dependencies {  
   compile fileTree(dir: 'libs', include: ['*.jar'])  
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {  
     exclude group: 'com.android.support', module: 'support-annotations'  
   })  
   compile 'com.android.support:appcompat-v7:24.2.1'  
   compile 'com.android.support:cardview-v7:24.2.0'  
   compile 'com.android.support:recyclerview-v7:24.2.0'  
   compile 'com.github.bumptech.glide:glide:3.7.0'  
   testCompile 'junit:junit:4.12'  
 }  

Add the above dependency and click on sync button to sync the project with added dependency.
Our project is ready now we can add our recycler view to activity_main.xml layout file so open the activity_main.xml files add the Recycler view, after adding the recycler view our activity_main.xml will look like as given below.
activity_main.xml

 <?xml version="1.0" encoding="utf-8"?>  
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
   xmlns:tools="http://schemas.android.com/tools"  
   android:id="@+id/activity_main"  
   android:layout_width="match_parent"  
   android:layout_height="match_parent"  
   tools:context="com.debugandroid.imagegallery.MainActivity">  
   <android.support.v7.widget.RecyclerView  
     android:layout_width="match_parent"  
     android:layout_height="match_parent"  
     android:id="@+id/recyclerView">  
   </android.support.v7.widget.RecyclerView>  
 </RelativeLayout>  

Create ItemView to display the image inside RecylcerView

Item view we will use an image view and text view, Image for showing the image and text view for displaying the name of the photo. Create a XML file with name of item_view.xml

 <?xml version="1.0" encoding="utf-8"?>  
 <android.support.v7.widget.CardView  
   xmlns:card_view="http://schemas.android.com/apk/res-auto"  
   xmlns:android="http://schemas.android.com/apk/res/android"  
   android:id="@+id/card_view"  
   android:layout_width="match_parent"  
   android:layout_height="wrap_content"  
   card_view:cardCornerRadius="1dp"  
   android:layout_margin="2dp">  
   <LinearLayout android:orientation="vertical"  
     android:layout_width="match_parent"  
     android:layout_height="wrap_content">  
     <android.support.v7.widget.CardView  
       android:layout_width="wrap_content"  
       android:layout_height="wrap_content"  
       card_view:cardCornerRadius="1dp"  
       android:layout_margin="0dp">  
       <ImageView  
         android:layout_width="200dp"  
         android:layout_height="100dp"  
         android:id="@+id/media_img_bck"  
         android:layout_gravity="center"  
         android:scaleType="fitXY"  
         />  
     </android.support.v7.widget.CardView>  
     <LinearLayout  
       android:layout_width="match_parent"  
       android:layout_height="wrap_content"  
       android:orientation="vertical"  
       android:weightSum="1">  
       <TextView  
         android:layout_marginTop="5dp"  
         android:layout_marginLeft="5dp"  
         android:layout_width="match_parent"  
         android:layout_height="wrap_content"  
         android:text="Title"  
         android:gravity="left|top"  
         android:id="@+id/media_name"  
         android:textColor="@android:color/primary_text_light"  
         android:layout_gravity="center_vertical"  
         android:layout_weight="0.60"  
         android:textSize="12sp"/>  
     </LinearLayout>  
   </LinearLayout>  
 </android.support.v7.widget.CardView>  

Creating ImageItem template class

We need to create a class for our item to show the data type with getter and setter.
ImageItem.java

 package com.debugandroid.imagegallery;  
 /**  
  * Created by Pawan.  
  */  
 public class ImageItem {  
   String DATA;  
   String DISPLAY_NAME;  
   String CREATED;  
   public ImageItem(String DATA, String DISPLAY_NAME,String CREATED){  
     this.DATA=DATA;  
     this.DISPLAY_NAME=DISPLAY_NAME;  
     this.CREATED=CREATED;  
   };  
   public ImageItem(){  
   }  
   public String getDATA() {  
     return DATA;  
   }  
   public void setDATA(String DATA) {  
     this.DATA = DATA;  
   }  
   public String getDISPLAY_NAME() {  
     return DISPLAY_NAME;  
   }  
   public void setDISPLAY_NAME(String DISPLAY_NAME) {  
     this.DISPLAY_NAME = DISPLAY_NAME;  
   }  
   public String getCREATED() {  
     return CREATED;  
   }  
   public void setCREATED(String CREATED) {  
     this.CREATED = CREATED;  
   }  
 }  

We create a class MediaQuery.java to extract the all image URI from sd card. Create a class and modify it as given below.

MediaQuery.java

 package com.debugandroid.imagegallery;  
 import android.content.Context;  
 import android.database.Cursor;  
 import android.provider.MediaStore;  
 import java.io.File;  
 import java.text.SimpleDateFormat;  
 import java.util.ArrayList;  
 import java.util.Calendar;  
 import java.util.List;  
 /**  
  * Created by Pawan.  
  */  
 public class MediaQuery {  
   private Context context;  
   private int count = 0;  
   private Cursor cursor;  
   List<ImageItem> imageItems;  
   public MediaQuery(Context context){  
     this.context=context;  
   }  
   public List<ImageItem> getAllImage() {  
     String selection = null;  
     cursor = context.getContentResolver().query(  
         MediaStore.Images.Media.EXTERNAL_CONTENT_URI,  
         null,  
         selection,  
         null,  
         null);  
     imageItems = new ArrayList<ImageItem>();  
     ImageItem imageItem;  
     while (cursor.moveToNext()) {  
       imageItem = new ImageItem();  
       imageItem.setDATA(cursor.getString(1));  
       imageItem.setCREATED(getCreatedDate(cursor.getString(1)));  
       imageItem.setDISPLAY_NAME(getFileName(cursor.getString(1)));  
       imageItems.add(imageItem);  
     }  
   return imageItems;  
   }  
   public static String getCreatedDate(String filePath){  
     File file =new File(filePath);  
     long currentTime=System.currentTimeMillis();  
     long lastmodified=file.lastModified();  
     String createdTime;  
     SimpleDateFormat formatter = new SimpleDateFormat("HH:MM dd-MM-yyyy");  
     Calendar calendar = Calendar.getInstance();  
     calendar.setTimeInMillis(lastmodified);  
     return formatter.format(calendar.getTime());  
   }  
   public static String getFileName(String path) {  
     if (path == null || path.length() == 0) {  
       return "";  
     }  
     int query = path.lastIndexOf('?');  
     if (query > 0) {  
       path = path.substring(0, query);  
     }  
     int filenamePos = path.lastIndexOf(File.separatorChar);  
     return (filenamePos >= 0) ? path.substring(filenamePos + 1) : path;  
   }  
 }  

Create Adapter for Image Gallery

We create an adapter for our recycler view which will show the image in recycler view.
MyAdapter.java

 package com.debugandroid.imagegallery;  
 import android.content.Context;  
 import android.content.Intent;  
 import android.net.Uri;  
 import android.os.Bundle;  
 import android.support.v7.widget.RecyclerView;  
 import android.view.LayoutInflater;  
 import android.view.View;  
 import android.view.ViewGroup;  
 import android.view.animation.AlphaAnimation;  
 import android.view.animation.Animation;  
 import android.view.animation.ScaleAnimation;  
 import android.widget.ImageView;  
 import android.widget.TextView;  
 import com.bumptech.glide.Glide;  
 import java.util.List;  
 /**  
  * Created by Pawan on 2/20/2016.  
  */  
 public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {  
   private List<ImageItem> videoList;  
   Context context;  
   private final static int FADE_DURATION = 1000;  
   public static Glide glid;  
   String name;  
   Bundle bundle=new Bundle();  
   private static final int TYPE_ITEM = 1;  
   public MyAdapter(List<ImageItem> videoList, Context context) {  
     this.videoList = videoList;  
     this.context=context;  
   }  
   @Override  
   public int getItemViewType(int position) {  
     return TYPE_ITEM;  
   }  
   @Override  
   public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {  
       View itemView = LayoutInflater.  
           from(viewGroup.getContext()).  
           inflate(R.layout.item_view, viewGroup, false);  
       VideoViewHolder holder = new VideoViewHolder(itemView);  
       itemView.setTag(holder);  
       return holder;  
     }  
   @Override  
   public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {  
       ImageItem mediaObject=getItem(position);  
       name=mediaObject.getDISPLAY_NAME();  
       if (name.length() > 25) {  
        ((VideoViewHolder) holder).vName.setText(name.substring(0, 25) + "..");  
        } else {  
        ((VideoViewHolder) holder).vName.setText(name);  
        }  
       ((VideoViewHolder) holder).vImage.setImageResource(R.color.cardview_dark_background);  
       ((VideoViewHolder) holder).vFilePath = mediaObject.getDATA();  
       ((VideoViewHolder) holder).context = context;  
       ((VideoViewHolder) holder).position = position;  
       glid.with(context)  
           .load(mediaObject.getDATA())  
           .centerCrop()  
           .placeholder(R.color.cardview_dark_background)  
           .crossFade()  
           .into(((VideoViewHolder) holder).vImage);  
       setScaleAnimation(((VideoViewHolder) holder).vImage);  
   }  
   private void setScaleAnimation(View view) {  
     ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);  
     anim.setDuration(FADE_DURATION);  
     view.startAnimation(anim);  
   }  
   private void setFadeAnimation(View view) {  
     AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);  
     anim.setDuration(FADE_DURATION);  
     view.startAnimation(anim);  
   }  
   @Override  
   public void onAttachedToRecyclerView(RecyclerView recyclerView) {  
     super.onAttachedToRecyclerView(recyclerView);  
   }  
   @Override  
   public int getItemCount() {  
     int itemCount = videoList.size();  
     return itemCount;  
   }  
   private boolean isPositionHeader(int position) {  
     return position == 0;  
   }  
   private boolean isPositionFooter(int position) {  
     return position == getItemCount() - 1;  
   }  
   protected ImageItem getItem(int position) {  
     return videoList.get(position);  
   }  
   private int getItemPosition(int position){  
     return position;  
   }  
   public class VideoViewHolder extends RecyclerView.ViewHolder {  
     protected ImageView vImage;  
     protected TextView vName;  
     protected String vFilePath;  
     protected Context context;  
     protected int position;  
     public VideoViewHolder(View v) {  
       super(v);  
       vName = (TextView) v.findViewById(R.id.media_name);  
       vImage = (ImageView) v.findViewById(R.id.media_img_bck);  
       v.setOnClickListener(new View.OnClickListener() {  
         @Override  
         public void onClick(View v) {  
           Intent intent = new Intent();  
           intent.setAction(Intent.ACTION_VIEW);  
           intent.setData(Uri.parse(vFilePath));  
           intent.setDataAndType(Uri.parse(vFilePath), "image/*");  
           context.startActivity(intent);  
         }  
       });  
     }  
   }  
 }  

Finally, open MainActivity.java and modify it as given below.

 package com.debugandroid.imagegallery;  
 import android.Manifest;  
 import android.content.DialogInterface;  
 import android.content.pm.PackageManager;  
 import android.os.Build;  
 import android.provider.MediaStore;  
 import android.support.v7.app.AlertDialog;  
 import android.support.v7.app.AppCompatActivity;  
 import android.os.Bundle;  
 import android.support.v7.widget.GridLayoutManager;  
 import android.support.v7.widget.RecyclerView;  
 import android.util.Log;  
 import android.widget.Toast;  
 import java.util.ArrayList;  
 import java.util.HashMap;  
 import java.util.List;  
 import java.util.Map;  
 public class MainActivity extends AppCompatActivity {  
   private MediaQuery mediaQuery;  
   private List<ImageItem> imageItemList;  
   private RecyclerView recyclerView;  
   private MyAdapter imageAdapter;  
   final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;  
   @Override  
   protected void onCreate(Bundle savedInstanceState) {  
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.activity_main);  
     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){  
       checkandAskPermission();  
     }  
     else {  
       initMedia();  
     }  
   }  
   private void initMedia(){  
     recyclerView= (RecyclerView) findViewById(R.id.recyclerView);  
     imageItemList=new ArrayList<ImageItem>();  
     mediaQuery=new MediaQuery(this);  
     imageItemList=mediaQuery.getAllImage();  
     Log.d("ImageList","Count:"+imageItemList.size());  
     imageAdapter=new MyAdapter(imageItemList,this);  
     GridLayoutManager glm = new GridLayoutManager(this, 2);  
     glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {  
       @Override  
       public int getSpanSize(int position) {  
         switch (imageAdapter.getItemViewType(position)) {  
           case 0:  
             return 2;  
           case 1:  
             return 1;  
           case 2:  
             return 2;  
           default:  
             return 1;  
         }  
       }  
     });  
     recyclerView.setLayoutManager(glm);  
     recyclerView.setAdapter(imageAdapter);  
   }  
   private void checkandAskPermission() {  
     List<String> permissionsNeeded = new ArrayList<String>();  
     final List<String> permissionsList = new ArrayList<String>();  
     if (!addPermission(permissionsList, Manifest.permission.READ_EXTERNAL_STORAGE))  
       permissionsNeeded.add("Storage");  
     if (permissionsList.size() > 0) {  
       if (permissionsNeeded.size() > 0) {  
         String message = "You need to grant access to " + permissionsNeeded.get(0);  
         for (int i = 0; i < permissionsNeeded.size(); i++)  
           message = message + ", " + permissionsNeeded.get(i);  
         showMessageOKCancel(message,  
             new DialogInterface.OnClickListener() {  
               @Override  
               public void onClick(DialogInterface dialog, int which) {  
                 requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),  
                     REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);  
               }  
             });  
         return;  
       }  
       requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),  
           REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);  
       return;  
     }  
     initMedia();  
   }  
   private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {  
     new AlertDialog.Builder(this)  
         .setMessage(message)  
         .setPositiveButton("OK", okListener)  
         .setNegativeButton("Cancel", okListener)  
         .create()  
         .show();  
   }  
   private boolean addPermission(List<String> permissionsList, String permission) {  
     if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {  
       permissionsList.add(permission);  
       if (!shouldShowRequestPermissionRationale(permission))  
         return false;  
     }  
     return true;  
   }  
   @Override  
   public void onRequestPermissionsResult(int requestCode, String[] permissions,  
                       int[] grantResults){  
     switch (requestCode) {  
       case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {  
         Map<String, Integer> perms = new HashMap<String, Integer>();  
         perms.put(Manifest.permission.READ_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);  
         for (int i = 0; i < permissions.length; i++)  
           perms.put(permissions[i], grantResults[i]);  
         if (perms.get(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {  
           initMedia();  
         }  
         else {  
           // Permission Denied  
           Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT)  
               .show();  
         }  
       }  
     }  
   }  
 }  

Download the full source code from GitHub https://github.com/debugandroid/ImageGallery

Get Email Updates!

Signup now receive an email once I publish new content. I will never give away, trade or sell your email address. You can unsubscribe at any time.

Join 911 other subscribers

Leave a Reply

Close Menu