Android Capturing Images from Camera or Gallery as Bitmaps using ActivityResultLauncher

Hamza Asif
8 min readDec 2, 2022

--

Photo by Eaters Collective on Unsplash

Capturing images using a camera and using it in your Android applications can be tricky at times but the process is quite simple.

So in this story, I will teach you to get images from the gallery or capture images using a camera and then get those images as bitmaps in our applications.

Note: Learn the use of machine learning and computer vision in Android, Flutter & React Native with our Mobile Machine Learning courses. You can avail discount on the following Android machine-learning courses

  1. Android & Google Gemini — Build Smart Android Kotlin Apps
  2. Face Recognition and Detection in Android- The 2024 Guide
  3. Train Object Detection Models for Android — The 2024 Guide
  4. Android ML — Train Tensorflow Lite Models for Android Apps
  5. ChatGPT & Android — Build Chatbots & Smart Apps for Android
  6. Machine Learning use in Android — The 2024 Guide

So firstly create a new Android Studio project and select Java as the programming language. For Kotlin click here.

Layout

Now in the activity_main.xml file place an ImageView and two buttons. So replace activity_main.xml code with blow code..

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="0dp"
android:layout_height="0dp"
android:layout_marginStart="40dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="40dp"
android:layout_marginBottom="40dp"
app:layout_constraintBottom_toTopOf="@+id/button2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars" />

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp"
android:text="Gallery"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/button2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp"
android:text="Camera"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/button" />
</androidx.constraintlayout.widget.ConstraintLayout>

So we have placed an imageView to display the image that the user will choose or capture. And we added two buttons, one is for choosing images from the gallery and the second one is for capturing images using the camera. Now inside MainActivity create and initialize this imageview and buttons.

    ImageView imageView;
Button galleryBtn,cameraBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

imageView = findViewById(R.id.imageView);
galleryBtn = findViewById(R.id.button);
cameraBtn = findViewById(R.id.button2);
}

Choosing Images from the gallery

Let’s say we want to choose an image from the gallery when the user will click on the gallery button that we placed earlier inside our application layout.

So for that purpose, we need to set an OnClickListener on our button and launch an intent to open the gallery.

So inside the onCreate method set OnClick listener for the galleryBtn.

//TODO chose image from gallery
galleryBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
galleryActivityResultLauncher.launch(galleryIntent);
}
});

Now you can see the error for this galleryActivityResultLauncher. So starting from AndroidX to launch an intent we need to create an object of the type ActivityResultLauncher and then by using it we are going to launch the intent. So above onCreate method declare and initialize ActivityResultLauncher by pasting this code.

//TODO get the image from gallery and display it
ActivityResultLauncher<Intent> galleryActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {

}
});

Now there you can see when the user will click on the galleryBtn we are launching an intent to open the gallery. And once the user will select an image onActivityResult method of ActivityResultLauncher will be called and we can get the URI of the selected image inside that method and display it inside our imageView. So add this code inside the onActivityResult method

if (result.getResultCode() == Activity.RESULT_OK) {
Uri image_uri = result.getData().getData();
imageView.setImageURI(image_uri);
}

So inside this method, we are getting chosen image Uri and displaying that image inside our image view.

Now when you will run this application you will be able to choose an image from the gallery. So let’s test the application.

Capturing images using Camera

Now let’s add the code to capture the image using the camera and display it inside our application.

Permissions

As we want to capture images from the camera so we need the camera permission and then to save those images we need storage permission so in the manifest file add these lines

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>

Ask for these permissions dynamically inside MainActivity. So add these lines inside the onCreate method of MainActivity.

//TODO ask for permission of camera upon first launch of application
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_DENIED){
String[] permission = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permission, 112);
}
}

So now we want to open the camera and capture the image when the user will click on cameraBtn. Then we want to display that captured image inside our Android application inside the imageView.

So to achieve that set OnClickListener on the cameraBtn. So inside onCreate method paste the below code.

//TODO captue image using camera
cameraBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_DENIED){
String[] permission = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permission, 112);
}
else {
openCamera();
}
}
else {
openCamera();
}
}
});

So inside this method, we are again checking if the camera and storage permission is granted or not. If the permission is not granted then we are asking for permission again otherwise we are calling a method name openCamera. So Inside this method, we have the code to launch the camera. So place this code below onCreate method.

    Uri image_uri;
//TODO opens camera so that user can capture image
private void openCamera() {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "New Picture");
values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera");
image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);
cameraActivityResultLauncher.launch(cameraIntent);
}

//TODO capture the image using camera and display it
ActivityResultLauncher<Intent> cameraActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {

}
});

Now we have added the openCamera method along with cameraActivityResultLauncher. So inside this openCamera method, we are launching an intent using this cameraActivityResultLauncher to open the camera and capture an image.

And once the user will capture the image then the URI of that image will be stored inside the image_uri variable and onActivityResult method of cameraActivityResultLauncher will be called. So inside this method, we can simply display the captured image inside our imageView. So add these lines inside the onActivityResult method.

  if (result.getResultCode() == Activity.RESULT_OK) {
imageView.setImageURI(image_uri);
}

Now you can run the application and capture the image by clicking on the camera button.

Converting Image into bitmap

Now we are choosing or capturing images inside our android application but to get the image in a bitmap format place these uriToBitmap & rotateBitmap methods inside MainActivity.

//TODO takes URI of the image and returns bitmap
private Bitmap uriToBitmap(Uri selectedFileUri) {
try {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(selectedFileUri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

//TODO rotate image if image captured on samsung devices
//TODO Most phone cameras are landscape, meaning if you take the photo in portrait, the resulting photos will be rotated 90 degrees.
@SuppressLint("Range")
public Bitmap rotateBitmap(Bitmap input){
String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
Cursor cur = getContentResolver().query(image_uri, orientationColumn, null, null, null);
int orientation = -1;
if (cur != null && cur.moveToFirst()) {
orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
}
Log.d("tryOrientation",orientation+"");
Matrix rotationMatrix = new Matrix();
rotationMatrix.setRotate(orientation);
Bitmap cropped = Bitmap.createBitmap(input,0,0, input.getWidth(), input.getHeight(), rotationMatrix, true);
return cropped;
}

Here uriToBitmap is used to convert an image into a bitmap format and then we will pass that bitmap to rotateBitmap method so that we can get that bitmap in portrait orientation. In most cases when we capture an image using the camera the captured image is in landscape orientation. So we are using this rotateBitmap method to ensure that we get that image is in portrait mode in a bitmap format.

Now call these methods inside onActivityResult method of both cameraActivityResultLauncher and galleryActivityResultLauncher. So the code inside onActivityResult of cameraActivityResultLauncher will look like this

ActivityResultLauncher<Intent> cameraActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Bitmap inputImage = uriToBitmap(image_uri);
Bitmap rotated = rotateBitmap(inputImage);
imageView.setImageBitmap(rotated);

}
}
});

And the code inside onActivityResult of galleryActivityResultLauncher will look like this

//TODO get the image from gallery and display it
ActivityResultLauncher<Intent> galleryActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Uri image_uri = result.getData().getData();
imageView.setImageURI(image_uri);
}
}
});

And that’s it. Now when you will run this application you will be able to capture an image from the camera and then that image will be displayed inside imageView. As we also converted that image into a bitmap so you can use it for a variety of different purposes like for Performing different Machine Learning related operations.

So the complete code of our MainActivity will look like this

package com.example.imagepicker;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.FileDescriptor;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
//TODO get the image from gallery and display it
ActivityResultLauncher<Intent> galleryActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Uri image_uri = result.getData().getData();
imageView.setImageURI(image_uri);
}
}
});

ImageView imageView;
Button galleryBtn,cameraBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//TODO ask for permission of camera upon first launch of application
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_DENIED){
String[] permission = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permission, 112);
}
}

imageView = findViewById(R.id.imageView);
galleryBtn = findViewById(R.id.button);
cameraBtn = findViewById(R.id.button2);

galleryBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
galleryActivityResultLauncher.launch(galleryIntent);
}
});

cameraBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_DENIED){
String[] permission = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permission, 112);
}
else {
openCamera();
}
}
else {
openCamera();
}
}
});
}

Uri image_uri;
//TODO opens camera so that user can capture image
private void openCamera() {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "New Picture");
values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera");
image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);
cameraActivityResultLauncher.launch(cameraIntent);
}

//TODO capture the image using camera and display it
ActivityResultLauncher<Intent> cameraActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Bitmap inputImage = uriToBitmap(image_uri);
Bitmap rotated = rotateBitmap(inputImage);
imageView.setImageBitmap(rotated);

}
}
});

//TODO takes URI of the image and returns bitmap
private Bitmap uriToBitmap(Uri selectedFileUri) {
try {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(selectedFileUri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

//TODO rotate image if image captured on samsung devices
//TODO Most phone cameras are landscape, meaning if you take the photo in portrait, the resulting photos will be rotated 90 degrees.
@SuppressLint("Range")
public Bitmap rotateBitmap(Bitmap input){
String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
Cursor cur = getContentResolver().query(image_uri, orientationColumn, null, null, null);
int orientation = -1;
if (cur != null && cur.moveToFirst()) {
orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
}
Log.d("tryOrientation",orientation+"");
Matrix rotationMatrix = new Matrix();
rotationMatrix.setRotate(orientation);
Bitmap cropped = Bitmap.createBitmap(input,0,0, input.getWidth(), input.getHeight(), rotationMatrix, true);
return cropped;
}
}

Mobile Machine Learning

Learn the use of machine learning and computer vision in Android, Flutter & React Native with our Mobile Machine Learning courses. You can avail discount on the following Mobile Machine learning courses

Android Machine Learning Courses

Face Recognition in Android — Build Attendance Systems

Train Object Detection Models & build Android Applications

ChatGPT & Android — Build Chatbots & Smart Apps for Android

Android Machine Learning with TensorFlow lite in Java/Kotlin

Android & Regression: Train Prediction ML models for Android

Flutter Machine Learning Courses

Machine Learning for Flutter The Complete 2023 Guide

Face Recognition and Detection in Flutter — The 2024 Guide

Flutter and Linear Regression: Build Prediction Apps Flutter

ChatGPT & Flutter: Build Chatbots & Assistants in Flutter

Train Object Detection and classification models for Flutter

React Native Courses

ChatGPT & React Native — Build Chatbots for Android & IOS

Connect With Me

My Courses: https://www.udemy.com/user/e1c14fb5-1c9b-45ef-a479-bbc543e33254/

My Facebook: https://www.facebook.com/MobileMachineLearning

Youtube Channel: https://www.youtube.com/channel/UCuM6FHbMdYXQCR8syEtnM9Q

--

--

Hamza Asif
Hamza Asif

Written by Hamza Asif

Udemy Instructor, Flutter Dev helping people Integrate ML & AI in Mobile Apps . Visit my courses https://www.udemy.com/user/e1c14fb5-1c9b-45ef-a479-bbc543e33254

Responses (2)