Open native Android Camera and Photo Gallery in Java – XSTutorials

Open native Android Camera and Photo Gallery in Java

PLEASE NOTE: This tutorial has been written using Android Studio 3.5 and Java

In this tutorial, you’ll learn how to open the native Camera and Gallery of your device and display the picked image into an ImageView.

The Android Studio project

Let’s open a new Android Studio project (read this article to see how to do that). Name your project as CameraGallery and save it on your Desktop.

The Design

Open the activity_main.xml from the res/layout folder, switch to the Text preview and replace:

<androidx.constraintlayout.widget.ConstraintLayout 

with this:

<RelativeLayout

This is for you to better align Views in the Design screen since a RelativeLayout is more flexible than a ConstraintLayout.

Use RelativeLayout for your app Design

Switch back to the Design tab and start preparing your screen by dragging a few Views in it: an ImageView and two Buttons. You can either adjust their size and position in the Design tab, anyway, for the sake of this tutorial, I’ll post the code of the activity_main.xml file that will do that for you (paste it in the Text tab):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="240dp"
        android:layout_below="@id/textView"
        android:layout_marginTop="24dp"
        android:scaleType="centerCrop" />

    <Button
        android:id="@+id/cameraButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/imageView"
        android:layout_marginStart="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="20dp"
        android:text="Camera"
        android:textAllCaps="false" />

    <Button
        android:id="@+id/galleryButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/cameraButton"
        android:layout_marginStart="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="20dp"
        android:text="Gallery"
        android:textAllCaps="false" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="@string/app_name"
        android:textAlignment="center"
        android:textColor="#121212"
        android:textSize="24sp"
        android:textStyle="bold" />

</RelativeLayout>

This is how the activity_main.xml looks like:

The Code

Open the Manifest.xml file in the Editor and paste these permissions on the top of it:

<!-- Permissions -->
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Then open the MainActivity.java file and declare the following Views right above the onCreate() function:

ImageView myImageView;
Button cameraButton, galleryButton;

Declare the following variables below those instances:

Context ctx = this;
public static final int MULTIPLE_PERMISSIONS = 10;
public static String[] permissions= new String[]{
         Manifest.permission.WRITE_EXTERNAL_STORAGE,
         Manifest.permission.READ_EXTERNAL_STORAGE,
         Manifest.permission.CAMERA
};

It’s time to initialize our Views, so paste this code into the onCreate() function:

// Initialize Views
myImageView = findViewById(R.id.imageView);
cameraButton = findViewById(R.id.cameraButton);
galleryButton = findViewById(R.id.galleryButton);

Below those initializations, you need to create the onClickListener() instances for the Buttons in your screen:

//-----------------------------------------------
// MARK - CAMERA BUTTON
//-----------------------------------------------
cameraButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (!checkPermissions()) { checkPermissions();
        } else { openCamera(); }
}});


//-----------------------------------------------
// MARK - GALLERY BUTTON
//-----------------------------------------------
galleryButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (!checkPermissions()) { checkPermissions();
        } else { openGallery(); }
}});

Since we are calling the checkPermissions() function in both buttons, let’s create it before the end of our Java file:

//-----------------------------------------------
// MARK - CHECK FOR PERMISSIONS
//-----------------------------------------------
private  boolean checkPermissions() {
      int result;
      List<String> listPermissionsNeeded = new ArrayList<>();
      for (String p : permissions) {
         result = ContextCompat.checkSelfPermission(this, p);
         if (result != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(p);
         }
      }
      if (!listPermissionsNeeded.isEmpty()) {
         ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[0]), MULTIPLE_PERMISSIONS);
         return false;
      }
      return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  if (requestCode == MULTIPLE_PERMISSIONS) {
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        Log.i("log-", "ALL PERMISSIONS GRANTED!");
     }
  }
}

The method above is needed for Privacy reasons and checks if the Camera and Write/Read External Storage permissions have been accepted by the user – when you run the app for the first time, an alert shows up asking you to allow permissions).

Let’s create a new XML file that will help us in handling the onActivityResult() function to get our picked image. Right-click on the res folder and select New -> Android Resource File. In the popup window that will appear, type provider_paths as File name and choose XML from the Resource type dropdown list. Then click the OK button.

Create a provider_paths.xml file

Open the provider_paths.xml file you’ve just created – it’s into the res/xml folder – and replace its code with this one:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

Now, in theManifest.xml file, paste the following code before the </application> closure:

<!-- file provider -->
<provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true"
        tools:ignore="WrongManifestParent">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
</provider>

Go back to the MainActivity.java file and paste this code below the end of the onCreate() function:

int CAMERA = 0;
int GALLERY = 1;
Uri imageURI;
File file;

// OPEN CAMERA
public void openCamera() {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    file = new File(Environment.getExternalStorageDirectory(), "image.jpg");
    imageURI = FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".provider", file);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageURI);
    startActivityForResult(intent, CAMERA);
}

// OPEN GALLERY
public void openGallery() {
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select Image"), GALLERY);
}

// IMAGE/VIDEO PICKED DELEGATE ------------------------------
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);

       if (resultCode == Activity.RESULT_OK) {
          Bitmap bmp;

           // • IMAGE FROM CAMERA
           if (requestCode == CAMERA) {
               try {
                   File f = file;
                   ExifInterface exif = new ExifInterface(f.getPath());
                   int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

                   int angle = 0;
                   if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
                       angle = 90;
                   } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
                       angle = 180;
                   } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
                       angle = 270;
                   }
                   // Log.i("log-", "ORIENTATION: " + orientation);

                   Matrix mat = new Matrix();
                   mat.postRotate(angle);

                   bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, null);
                   assert bmp != null;
                   bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
                   bmp = scaleBitmapToMaxSize(600, bmp);

                   myImageView.setImageBitmap(bmp);

               } catch (IOException | OutOfMemoryError e) { Log.i("log-", e.getMessage()); }



           // • IMAGE FROM GALLERY
           } else if (requestCode == GALLERY) {
              try {
                 bmp = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), data.getData());
                 bmp = scaleBitmapToMaxSize(600, bmp);

                 myImageView.setImageBitmap(bmp);

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

       }// ./ If RESULT_OK
}

Due to the fact that some Android 7.0 devices don’t support big-sized images, we need to make sure that our taken picture won’t be too big for such phones. Therefore, we have to create a function that will proportionally scale our picked image.

Paste this code right below the end of the above method:

public static Bitmap scaleBitmapToMaxSize(int maxSize, Bitmap bm) {
       int outWidth;
       int outHeight;
       int inWidth = bm.getWidth();
       int inHeight = bm.getHeight();
       if(inWidth > inHeight){
           outWidth = maxSize;
           outHeight = (inHeight * maxSize) / inWidth;
       } else {
           outHeight = maxSize;
           outWidth = (inWidth * maxSize) / inHeight;
       }
       return Bitmap.createScaledBitmap(bm, outWidth, outHeight, false);
}

That’s all for the code, your app is ready. Plug your device’s cable into the USB port of your computer, select your device in the AVD list and hit the green Play button in Android Studio to run and test your app.

This is how your app should look like:

Conclusion

That’s all for this tutorial, you have learned how to open the native Camera and Gallery in an Android app.

Hope you enjoyed this article, feel free to post comments about it. You can also download the full Android Studio project of this tutorial, just click the link below:

Download the Android Studio project

Buy me a coffee - XScoder - thanks for your support
Your support will be highly appreciated 😉