Skip to main content

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:


https://www.nplix.com/create-image-video-thumbnail-android/

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

Comments

Popular posts from this blog

Flutter How to Start Android Activity from Flutter View

Flutter and Dart is an excellent combination for creating the UI, but for accessing the platform-specific service we need to open platform-specific activity. So lets in this article we will explore how to start an android activity and access the service from Flutter View. Create a Project for this Android Activity Flutter View Demo Create a Project From File menu select the New Flutter Project Enter the project name Select the AndroidX support and click on next After the above, we step click on Finish We will have the following project structure created. Create the Second Activity in Android Just go to the android folder and open it in separate windows. We will have the following project structure. Create the Activity Just right-click on the Kotlin folder and create a blank activity from the menu. If you create the activity then you may be required to upgrade the Gradle and do some import. So Just click on update and wait for the project s...

Kotlin Parcelable Array Objects Send To Activity

We know that IPC (Inter Process Communication) between the activity is an extremely important part of any application development. We often required that we need to send some data to other activity. For example, we may be required to send an array of data, data could be an Integer, String, Long, Double, Float or any other custom data objects. So, In this example, we are going to learn how to implement the Kotlin Parcelable Array object to send the data from one activity to second activity. What is Parcel? The parcel class is designed as a high-performance IPC transport. A Parcel can contain both flattened data that will be unflattened on the other side of the IPC, and references to live IBinde r objects that will result in the other side receiving a proxy IBinder connected with the original IBinder in the Parcel. Create Kotlin Parcelable Array Objects Parcelable is API for placing the arbitrary objects into the Parcel. In Actual in android app development, Parcelable is an interface ...

Scan and List All Available WiFi Network In Android

In this tutorial, we learn how to connect to a WiFi hotspot in android by code. In this Demo we will create an as small app which will scan the all available network or Hotspot and list down the network when you select specific network, the application will connect that particular network. You May Like Below Topic: How to Read and Write JSON data using GSON WP Android App using REST and volley WP Android App using REST and volley part2 Implementation of SwipeRefreshLayout in RecyclerView Create Amazing Bottom Navigation Bar Without Any External Library Introduction In this tutorial, we learn how to connect to a WiFi hotspot in android by code. In this Demo we will create an as small app which will scan the all available network or Hotspot and list down the network when you select specific network, the application will connect that particular network. We will add this functionality to our existing Demo app " Video Gallery ". If you would like to check out t...