How To Open Camera In Android Programmatically Using Intent

This article will show you an example about how to use intent to invoke android camera programmatically to take and save pictures. It will also tell you how to display those pictures one by one when user click one picture.

1. Invoke Android Camera Using Intent Example Overview.

android invoke camera programmatically example

As you can see from above GIF image. There is one button and one ImageView in the screen. When you click the button, the android camera app will popup, then you can take picture with it.

When you close the camera, the picture will be displayed in the image view object under the button.You can take several images, then when you click one image, it will show next image in the camera taken images list.

You can not run this example in android emulator. You need a physical android device which has camera. I use hua wei mate 8.

Before you can run it in physical device, you need enable USB debug mode in the physical device, Please read article How To Enable USB Debugging Mode On Android Device to learn more.

If you run this example in android emulator, you will find below exception be thrown.

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.media.action.IMAGE_PICTURE (has extras) }

android activity not found exception

2. Where The Pictures Are Saved In.

We save all the pictures in app external storage cache folder in this example. You can use below code to get android device external storage root folder.

 Environment.getExternalStorageDirectory()

Different android device may use different root folder. But generally external storage root folder is /sdcard, /mnt or /storage. But from below image, we can see that in hua wei mate 8, the root directory has been linked to /storage/41B7-12F1

huawei mate 8 sdcard link directory

So the app specific cache folder will be /storage/41B7-12F1/Android/data/com.dev2qa.example/cache. All the temporary camera taken pictures will be saved in this folder.

android app external storage cache folder

3. How To Save Those Pictures In Above Folder.

Camera app is responsible for saving the pictures in above folder. So you should tell camera app the folder path by using a Uri object. The Uri object is a wrapper of the picture file path. It is used to identify the resource’s ( file ) path uniquely.

Below is the code that pass output picture save folder to camera app using intent.

cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputImgUri)

After camera app take image, when you close the camera, you can find the picture files are saved by camera in below app specific cache directory.

camera taken images saved in app cache folder

4. How To Startup Camera Using Intent.

First you need create an Intent object with action MediaStore.ACTION_IMAGE_CAPTURE (android.media.action.IMAGE_CAPTURE).

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

Then put the output image uri as the extra parameter pass to camera activity.

cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputImgUri);

And then start the camera app and wait for camera app process result.

startActivityForResult(cameraIntent, REQUEST_CODE_TAKE_PICTURE);

5. Use FileProvider To Get Picture File Uri Wrapper.

From android OS version 7.0 ( sdk version 24 ), you need use android.support.v4.content.FileProvider class to share files between android apps.

Because those picture files are created by camera app, and only camera and camera same group user can read them, all other users can only execute them. You can get this conclusion from below picture.

camera taken images saved in app cache folder

So if you want to read those pictures file in this example app, you must use a content resolver to read them by their Uri.

FileProvider is a content provider which focus on file sharing. But before you can use it, you should configure it in AndroidManifest.xml file.

<!-- FileProvider settings, after this configuration you can use FileProvider in your activity. -->
<provider
    <!-- The authority of this file provider -->
    android:authorities="com.dev2qa.fileprovider"
    android:name="android.support.v4.content.FileProvider"
    android:exported="false"
    android:grantUriPermissions="true">

    <!-- Specify which folder will be shared by this file provider. -->
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/shared_file_paths" />
</provider>

Please remember the provider’s android:authorities attribute value, this value will be used as the second parameter of FileProvider.getUriForFile method when getting shared files uri.

ret = FileProvider.getUriForFile(ctx, "com.dev2qa.fileprovider", file);

The meta-data xml tag specify the shared file directories in a xml resource file. The file name is shared_file_paths.xml which saved in app / res / xml folder, but you can use any file name in your code as you like.

READ :   Android Pick Multiple Image From Gallery Example

android file provider share folder settings xml file

If the xml folder do not exist, you need do following to create it.

  1. Right click app / res folder.
  2. Click New —> Directory in popup menu.
  3. Enter xml for the directory name.

Below is the steps to create shared_file_paths.xml file.

  1. Right click app / res / xml folder.
  2. Click New —> XML resource file.
  3. Input the xml file name.

Now enter below xml content in shared_file_paths.xml.

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Configure shared external storage path, path value is relative to your device external storage root path ( /sdcard ). -->
    <external-path name="CameraPicture" path="Android/data/com.dev2qa.example/cache/" />
</paths>

6. Main Activity File.

TakePictureActivity.java

package com.dev2qa.example.camera;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import com.dev2qa.example.R;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class TakePictureActivity extends AppCompatActivity {

    // This tag is used for error or debug log.
    private static final String TAG_TAKE_PICTURE = "TAKE_PICTURE";

    // This is the request code when start camera activity use implicit intent.
    public static final int REQUEST_CODE_TAKE_PICTURE = 1;

    // This imageview is used to show camera taken picture.
    private ImageView takePictureImageView;

    // This output image file uri is used by camera app to save taken picture.
    private Uri outputImgUri;

    // Save the camera taken picture in this folder.
    private File pictureSaveFolderPath;

    // Save imageview currently displayed picture index in all camera taken pictures..
    private int currentDisplayImageIndex = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_take_picture);

        setTitle("dev2qa.com - Android Take Picture Example");

        // Get this app's external cache directory, manipulate this directory in app do not need android os system permission check.
        // The cache folder is application specific, when the app is uninstalled it will be removed also.
        pictureSaveFolderPath = getExternalCacheDir();

        // Get the display camera taken picture imageview object.
        takePictureImageView = (ImageView)findViewById(R.id.take_picture_image_view);

        // When you click the image view object, all the taken pictures will be shown one by one like slide.
        takePictureImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if(pictureSaveFolderPath!=null) {
                    // Get all camera taken pictures in picture save folder.
                    File imageFiles[] = pictureSaveFolderPath.listFiles();
                    if (imageFiles!=null)
                    {
                        // Get content resolver object.
                        ContentResolver contentResolver = getContentResolver();

                        int allImagesCount = imageFiles.length;

                        // If current display picture index is bigger than image count.
                        if(currentDisplayImageIndex >= allImagesCount-1)
                        {
                            currentDisplayImageIndex = 0;
                        }else
                        {
                            currentDisplayImageIndex++;
                        }

                        // Get to be displayed image file object.
                        File displayImageFile = imageFiles[currentDisplayImageIndex];

                        // Get display image Uri wrapped object.
                        Uri displayImageFileUri = getImageFileUriByOsVersion(displayImageFile);

                        try {
                            // Open display image input stream.
                            InputStream inputStream = contentResolver.openInputStream(displayImageFileUri);

                            // Decode the image input stream to a bitmap use BitmapFactory.
                            Bitmap pictureBitmap = BitmapFactory.decodeStream(inputStream);

                            // Set the image bitmap in the image view component to display it.
                            takePictureImageView.setImageBitmap(pictureBitmap);

                        }catch(FileNotFoundException ex) {
                            Log.e(TAG_TAKE_PICTURE, ex.getMessage(), ex);
                        }
                    }
                }
            }
        });

        // Get the take picture button object.
        Button takePictureButton = (Button)findViewById(R.id.take_picture_button);

        // When the button is clicked.
        takePictureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {

                    // Create a random image file name.
                    String imageFileName = "outputImage_" + System.currentTimeMillis() + ".png";

                    // Construct a output file to save camera taken picture temporary.
                    File outputImageFile = new File(pictureSaveFolderPath, imageFileName);

                    // If cached temporary file exist then delete it.
                    if (outputImageFile.exists()) {
                        outputImageFile.delete();
                    }

                    // Create a new temporary file.
                    outputImageFile.createNewFile();

                    // Get the output image file Uri wrapper object.
                    outputImgUri = getImageFileUriByOsVersion(outputImageFile);

                    // Startup camera app.
                    // Create an implicit intent which require take picture action..
                    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    // Specify the output image uri for the camera app to save taken picture.
                    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputImgUri);
                    // Start the camera activity with the request code and waiting for the app process result.
                    startActivityForResult(cameraIntent, REQUEST_CODE_TAKE_PICTURE);

                }catch(IOException ex)
                {
                    Log.e(TAG_TAKE_PICTURE, ex.getMessage(), ex);
                }
            }
        });
    }

    /* Get the file Uri object by android os version.
    *  return a Uri object. */
    private Uri getImageFileUriByOsVersion(File file)
    {
        Uri ret = null;

        // Get output image unique resource identifier. This uri is used by camera app to save taken picture temporary.
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
        {
            // /sdcard/ folder link to /storage/41B7-12F1 folder
            // so below code return /storage/41B7-12F1
            File externalStorageRootDir = Environment.getExternalStorageDirectory();

            // contextRootDir = /data/user/0/com.dev2qa.example/files in my Huawei mate 8.
            File contextRootDir = getFilesDir();

            // contextCacheDir = /data/user/0/com.dev2qa.example/cache in my Huawei mate 8.
            File contextCacheDir = getCacheDir();

            // For android os version bigger than or equal to 7.0 use FileProvider class.
            // Otherwise android os will throw FileUriExposedException.
            // Because the system considers it is unsafe to use local real path uri directly.
            Context ctx = getApplicationContext();
            ret = FileProvider.getUriForFile(ctx, "com.dev2qa.fileprovider", file);
        }else
        {
            // For android os version less than 7.0 there are no safety issue,
            // So we can get the output image uri by file real local path directly.
            ret = Uri.fromFile(file);
        }

        return ret;
    }

    /* This method is used to process the result of camera app. It will be invoked after camera app return.
    It will show the camera taken picture in the image view component. */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        try {
            // Process result for camera activity.
            if (requestCode == REQUEST_CODE_TAKE_PICTURE) {

                // If camera take picture success.
                if (resultCode == RESULT_OK) {

                    // Get content resolver.
                    ContentResolver contentResolver = getContentResolver();

                    // Use the content resolver to open camera taken image input stream through image uri.
                    InputStream inputStream = contentResolver.openInputStream(outputImgUri);

                    // Decode the image input stream to a bitmap use BitmapFactory.
                    Bitmap pictureBitmap = BitmapFactory.decodeStream(inputStream);

                    // Set the camera taken image bitmap in the image view component to display.
                    takePictureImageView.setImageBitmap(pictureBitmap);
                }
            }
        }catch(FileNotFoundException ex)
        {
            Log.e(TAG_TAKE_PICTURE, ex.getMessage(), ex);
        }
    }
}

7. Layout Xml File.

activity_take_picture.xml

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <Button
        android:id="@+id/take_picture_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Take A Picture"/>

    <ImageView
        android:id="@+id/take_picture_image_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

8. Android Manifest Xml File.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.dev2qa.example">

    <!-- Declare bellow permission to make this example 
         compatible with android os version smaller than 4.4. 
         Those version of android os require write external storage permission when write to sdcard. -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".camera.TakePictureActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- FileProvider settings, after this configuration you can use FileProvider in your activity. -->
        <provider
            android:authorities="com.dev2qa.fileprovider"
            android:name="android.support.v4.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">

            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/shared_file_paths" />
        </provider>
    </application>

</manifest>

9. File Provider Share Folder Configuration File.

shared_file_paths.xml

Please see chapter 5 in above content.

READ :   Android Hello World Example Project File Structure

android file provider share folder settings xml file

(Visited 7,584 times, 33 visits today)

1 Comment


  1. Has this solution been tested on Android 8.1, I tried implementing opening camera using startActivityForResult () but my application is killed before result is returned to the fragment.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.