How to Build a Photo Viewing Application in Android? - GeeksforGeeks

How to Build a Photo Viewing Application in Android?

Last Updated : 17 Oct, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Gallery app is one of the most used apps which comes pre-installed on many android devices and there are several different apps that are present in Google Play to view the media files present in your device. In this article, we will be simply creating a Gallery app in which we can view all the photos which we have stored on our device. Along with that, we can view individual photos in our app as well. 

What we are going to build in this article? 

We will be building a simple application in which we will be simply displaying the list of photos in the grid format and on clicking on the photo we can view that photo and can zoom in the photo to view it properly. Below is the vide0 in which we will get to see what we are going to build in this article. 

Step-by-Step Implementation

Step 1: Create a New Project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.

Step 2: Add the dependency in build.gradle file

Navigate to the app > Gradle Scripts > build.gradle(:app) and add the below dependency to it. We are using Picasso for loading images from paths in our ImageView

// below dependency for using Picasso image loading library

implementation ‘com.squareup.picasso:picasso:2.71828’

Now sync your project and we will move towards adding permissions in our AndroidManifest.xml file. 

Step 3: Adding permissions in our AndroidManifest.xml file

Navigate to the app > AndroidManifest.xml file and add the below permissions to it.

XML




<!-- permissions for reading external storage -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


 
 

As we are loading all the images from our storage at a time so we have to add 2 attributes to our application tag in the AndroidManifest.xml file. Navigate to the AndroidManifest.xml file and add below two lines in your application tag of Manifest file. 

 

XML




android:hardwareAccelerated="false"
android:largeHeap="true"


 
 

Step 4: Working with the activity_main.xml file

 

Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. 

 

XML




<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">
 
    <!--recycler view for displaying the list of images-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/idRVImages"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
 
</RelativeLayout>


 
 

Step 5: Creating an item for displaying in a RecyclerView 

 

Navigate to the app > res > layout > Right-click on it > New > layout Resource file and create a new layout resource file. Name the file as card_layout and add the below code to it. Comments are added in the code to get to know in more detail. 

 

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="3dp"
    android:elevation="8dp"
    app:cardCornerRadius="8dp">
 
    <!--Image view for displaying the image
        in our card layout in recycler view-->
    <ImageView
        android:id="@+id/idIVImage"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:scaleType="centerCrop" />
 
</androidx.cardview.widget.CardView>


 
 

Step 6: Creating a new activity for displaying a single image

 

Navigate to the app > java > your app’s package name > Right-click on it > New > Empty Activity and name your activity as ImageDetailActivity and create a new activity. We will be using this activity to display our single image from the list of different images. 

 

Step 7: Creating an adapter class for setting data to each item in our RecyclerView 

 

Navigate to the app > java > your app’s package name > Right-click on it > New Java class and name your class as RecyclerViewAdapter and add the below code to it. Comments are added in the code to get to know in more detail. 

 

Java




import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
 
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
 
import com.squareup.picasso.Picasso;
 
import java.io.File;
import java.util.ArrayList;
 
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {
     
    // creating a variable for our context and array list.
    private final Context context;
    private final ArrayList<String> imagePathArrayList;
 
    // on below line we have created a constructor.
    public RecyclerViewAdapter(Context context, ArrayList<String> imagePathArrayList) {
        this.context = context;
        this.imagePathArrayList = imagePathArrayList;
    }
 
    @NonNull
    @Override
    public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // Inflate Layout in this method which we have created.
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_layout, parent, false);
        return new RecyclerViewHolder(view);
    }
 
    @Override
    public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
         
        // on below line we are getting the file from the
        // path which we have stored in our list.
        File imgFile = new File(imagePathArrayList.get(position));
         
        // on below line we are checking if the file exists or not.
        if (imgFile.exists()) {
             
            // if the file exists then we are displaying that file in our image view using picasso library.
            Picasso.get().load(imgFile).placeholder(R.drawable.ic_launcher_background).into(holder.imageIV);
             
            // on below line we are adding click listener to our item of recycler view.
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                     
                    // inside on click listener we are creating a new intent
                    Intent i = new Intent(context, ImageDetailActivity.class);
                     
                    // on below line we are passing the image path to our new activity.
                    i.putExtra("imgPath", imagePathArrayList.get(position));
                     
                    // at last we are starting our activity.
                    context.startActivity(i);
                }
            });
        }
    }
 
    @Override
    public int getItemCount() {
        // this method returns
        // the size of recyclerview
        return imagePathArrayList.size();
    }
 
    // View Holder Class to handle Recycler View.
    public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
         
        // creating variables for our views.
        private final ImageView imageIV;
 
        public RecyclerViewHolder(@NonNull View itemView) {
            super(itemView);
            // initializing our views with their ids.
            imageIV = itemView.findViewById(R.id.idIVImage);
        }
    }
}


 
 

Step 8: Working with the MainActivity.java file

 

Go to the MainActivity.java file and refer to the following code. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.

 

Java




import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.widget.Toast;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
 
import java.util.ArrayList;
 
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 
public class MainActivity extends AppCompatActivity {
     
    // on below line we are creating variables for
    // our array list, recycler view and adapter class.
    private static final int PERMISSION_REQUEST_CODE = 200;
    private ArrayList<String> imagePaths;
    private RecyclerView imagesRV;
    private RecyclerViewAdapter imageRVAdapter;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         
         
         
        // creating a new array list and
        // initializing our recycler view.
        imagePaths = new ArrayList<>();
        imagesRV = findViewById(R.id.idRVImages);
       
          // we are calling a method to request
        // the permissions to read external storage.
        requestPermissions();
         
        // calling a method to
        // prepare our recycler view.
        prepareRecyclerView();
    }
 
    private boolean checkPermission() {
        // in this method we are checking if the permissions are granted or not and returning the result.
        int result = ContextCompat.checkSelfPermission(getApplicationContext(), READ_EXTERNAL_STORAGE);
        return result == PackageManager.PERMISSION_GRANTED;
    }
 
    private void requestPermissions() {
        if (checkPermission()) {
            // if the permissions are already granted we are calling
            // a method to get all images from our external storage.
            Toast.makeText(this, "Permissions granted..", Toast.LENGTH_SHORT).show();
            getImagePath();
        } else {
            // if the permissions are not granted we are
            // calling a method to request permissions.
            requestPermission();
        }
    }
     
    private void requestPermission() {
        //on below line we are requesting the read external storage permissions.
        ActivityCompat.requestPermissions(this, new String[]{READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
    }
 
    private void prepareRecyclerView() {
         
        // in this method we are preparing our recycler view.
        // on below line we are initializing our adapter class.
        imageRVAdapter = new RecyclerViewAdapter(MainActivity.this, imagePaths);
         
        // on below line we are creating a new grid layout manager.
        GridLayoutManager manager = new GridLayoutManager(MainActivity.this, 4);
         
        // on below line we are setting layout
        // manager and adapter to our recycler view.
        imagesRV.setLayoutManager(manager);
        imagesRV.setAdapter(imageRVAdapter);
    }
 
    private void getImagePath() {
        // in this method we are adding all our image paths
        // in our arraylist which we have created.
        // on below line we are checking if the device is having an sd card or not.
        boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
 
        if (isSDPresent) {
             
            // if the sd card is present we are creating a new list in
            // which we are getting our images data with their ids.
            final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID};
             
            // on below line we are creating a new
            // string to order our images by string.
            final String orderBy = MediaStore.Images.Media._ID;
             
            // this method will stores all the images
            // from the gallery in Cursor
            Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, orderBy);
             
            // below line is to get total number of images
            int count = cursor.getCount();
             
            // on below line we are running a loop to add
            // the image file path in our array list.
            for (int i = 0; i < count; i++) {
                 
                // on below line we are moving our cursor position
                cursor.moveToPosition(i);
                 
                // on below line we are getting image file path
                int dataColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
                 
                // after that we are getting the image file path
                // and adding that path in our array list.
                imagePaths.add(cursor.getString(dataColumnIndex));
            }
            imageRVAdapter.notifyDataSetChanged();
            // after adding the data to our
            // array list we are closing our cursor.
            cursor.close();
        }
    }
 
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        // this method is called after permissions has been granted.
        switch (requestCode) {
            // we are checking the permission code.
            case PERMISSION_REQUEST_CODE:
                // in this case we are checking if the permissions are accepted or not.
                if (grantResults.length > 0) {
                    boolean storageAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                    if (storageAccepted) {
                        // if the permissions are accepted we are displaying a toast message
                        // and calling a method to get image path.
                        Toast.makeText(this, "Permissions Granted..", Toast.LENGTH_SHORT).show();
                        getImagePath();
                    } else {
                        // if permissions are denied we are closing the app and displaying the toast message.
                        Toast.makeText(this, "Permissions denied, Permissions are required to use the app..", Toast.LENGTH_SHORT).show();
                    }
                }
                break;
        }
    }
}


 
 

Step 9: Working with the activity_image_detail.xml file. 

 

Navigate to the app > res > layout > activity_image_detail.xml and add the below code to that file. Below is the code for the activity_image_detail.xml file. 

 

XML




<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ImageDetailActivity">
 
    <!--image view to display our image-->
    <ImageView
        android:id="@+id/idIVImage"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_centerInParent="true" />
 
</RelativeLayout>


 
 

Step 10: Working with ImageDetailActivity.java file 

 

Go to the ImageDetailActivity.java file and refer to the following code. Below is the code for the ImageDetailActivity.java file. Comments are added inside the code to understand the code in more detail.

 

Java




import android.os.Bundle;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.ImageView;
 
import androidx.appcompat.app.AppCompatActivity;
 
import com.squareup.picasso.Picasso;
 
import java.io.File;
 
public class ImageDetailActivity extends AppCompatActivity {
     
    // creating a string variable, image view variable
    // and a variable for our scale gesture detector class.
    String imgPath;
    private ImageView imageView;
    private ScaleGestureDetector scaleGestureDetector;
     
    // on below line we are defining our scale factor.
    private float mScaleFactor = 1.0f;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_detail);
        
        // on below line getting data which we have passed from our adapter class.
        imgPath = getIntent().getStringExtra("imgPath");
         
        // initializing our image view.
        imageView = findViewById(R.id.idIVImage);
         
        // on below line we are initializing our scale gesture detector for zoom in and out for our image.
        scaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());
        
        // on below line we are getting our image file from its path.
        File imgFile = new File(imgPath);
         
        // if the file exists then we are loading that image in our image view.
        if (imgFile.exists()) {
            Picasso.get().load(imgFile).placeholder(R.drawable.ic_launcher_background).into(imageView);
        }
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent motionEvent) {
        // inside on touch event method we are calling on
        // touch event method and passing our motion event to it.
        scaleGestureDetector.onTouchEvent(motionEvent);
        return true;
    }
 
    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        // on below line we are creating a class for our scale
        // listener and  extending it with gesture listener.
        @Override
        public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
             
            // inside on scale method we are setting scale
            // for our image in our image view.
            mScaleFactor *= scaleGestureDetector.getScaleFactor();
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));
             
            // on below line we are setting
            // scale x and scale y to our image view.
            imageView.setScaleX(mScaleFactor);
            imageView.setScaleY(mScaleFactor);
            return true;
        }
    }
}


 
 

Now run your app and see the output of the app. 

 

Output:

 

Note: Make sure to grant read storage permissions. 

 



Previous Article
Next Article

Similar Reads

How to Build a Photo Viewing Application in Android using Jetpack Compose?
Gallery App is one of the most used Applications which comes pre-installed on many Android devices and there are several different applications that are present in Google Play to view the media files present in a device. In this article, we will be building a simple Gallery Application for Android using Jetpack Compose. In this application, we will
10 min read
Photo Picker in Android 13 with Example Project
In many android applications, we get to see that they are picking images from the user's device and displaying that images within the android application. For image picking, android applications use intent within the android application. In this article, we will take a look at How to implement Photo Picker in Android 13. A sample video is given bel
3 min read
How to Use Photo Picker in Android 13?
With Android 13, Google unveiled a new specialized media picker. This new option provides a more private and user-friendly alternative for those times when you want to share photographs, as opposed to potentially granting apps access to all of your files via the well-known document picker. You don't actually need Android 13 on your phone to use thi
4 min read
How to Build a ChatGPT Like Image Generator Application in Android?
Chat GPT is nowadays one of the famous AI tools which are like a chatbot. This chatbot answers all the queries which are sent to it. In this article, we will be building a simple ChatGPT-like android application in which we will be able to ask any question and from that question, we will be able to get an appropriate response in the form of images
5 min read
How to Build a TODO Android Application with AWS DynamoDB as Database?
This is a TODO application made on android studio IDE, code is written in JAVA, and data store in AWS DynamoDB and fetch to the home screen. The connection established between the application and AWS through Amplify CLI and the data is successful gets stored by creating a TODO Table in DynamoDB, a Schema is also created which shows the structure of
7 min read
How to Build Spin the Bottle Game Application in Android?
In this article, we will be building a Spin the Bottle Game Project using Java and XML in Android. The application is based on a multiplayer game. One player spins the bottle and the direction in which the bottle spins will determine the player who gets selected for a task or any other stuff. There will be a single activity in this application. A s
4 min read
How to Build an Application to Test Motion Sensors in Android?
In this article, we will be building a Motion Sensor Testing App Project using Java and XML in Android. The application will be using the hardware of the device to detect the movements. The components required to detect the motion are Accelerometer and Gyroscope. The Accelerometer is an electronic sensor used to detect the device's position in spac
6 min read
How to Build a Xylophone Application in Android?
In this article, we will be building a project on Xylophone using Java and XML in android. Xylophone originally is an instrument played by striking a row of wooden bars. This application will be implementing a Xylophone-like instrument that is capable of producing sounds. We will create few Buttons in this app that will act as keys of the instrumen
4 min read
How to Build a Step Counting Application in Android Studio?
Many of us have used the step counter on our phones while we go for walk or run. It counts the total steps that the user has walked and displays it on the screen. The other name for the step counter is a pedometer. But have you ever thought about how can an app count our steps? What is the coding behind the working of this app? Let's find the answe
6 min read
How to Get the Build Version Number of an Android Application?
Version Name and Version Code in an Android application tell us about the current app version installed on the user's mobile device. This information is generally used when we prompt users to update to the new version of the older version of the application. In this article, we will look at How to get the Build Version Number of an Android applicat
3 min read
Article Tags :
Practice Tags :