Capture photo

Android documentation Reference

1) Capture a photo by delegating the work to another camera app on the device. (Otherwise, we ll have to implement our own camera function, which will be discussed later)

2) Requires the following feature to be defined in AndroidManifest.xml

<uses-feature android:name="android.hardware.camera"
                  android:required="true" />

If your application uses, but does not require a camera in order to function, instead set android:required to false. In doing so, Google Play will allow devices without a camera to download your application. It's then your responsibility to check for the availability of the camera at runtime by calling

hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)

3) The Android way of delegating actions to other applications is to invoke an Intent. We need to set some code to handle the image data when focus returns to your activity.

static final int REQUEST_IMAGE_CAPTURE = 1;

    // this function may be called on button click
    private void dispatchTakePictureIntent() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // resolveActivity ensures that the camera app functions properly
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Pass in a request code, which will help handling 
            //what should be done after activity is returned
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            //Do something
        }
    }

Get thumbnail

It is not directly possible to get the actual photo from our app without knowing the path where the camera app saves the pics

However, the Android Camera application encodes the photo as a thumbnail (low quality) in the return Intent delivered to onActivityResult() as a small Bitmap in the extras, under the key "data".

@Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
                Bundle extras = data.getExtras();
                Bitmap imageBitmap = (Bitmap) extras.get("data");
                // low quality image
                mImageView.setImageBitmap(imageBitmap);
            }
        }

Get full photo

1) For this, we have to save the photo, and access it via its URI

2) This is done through FileProvider. For this, first decide where to store the file.

Storing the file private to app (Cannot be accessed via gallery) : Use the path,

getExternalFilesDir(Environment.DIRECTORY_PICTURES);
// storage/emulated/0/Android/data/com.aravindsankaran.takephotos/files/Pictures

Storing the file in public directory (Can be accessed via gallery)

getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
//storage/emulated/0/Pictures

3) Store these path in an XML file under resource directory, say res/xml/files_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--Path corresponds to getExternalFilesDir(Environment.DIRECTORY_PICTURES)-->
    <external-path name="my_images" path="Android/data/com.aravindsankaran.takephotos/files/Pictures" />
    <!--Path corresponds to getExternalStoragePublicDirectory(DIRECTORY_PICTURES)-->
    <external-path name="public_images" path="Pictures/" />
</paths>

4) In AndroidManifest.xml, create a provider element inside application and point file_paths.xml. Also set the WRITE EXTERNAL STORAGE permission

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application>
    ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.aravindsankaran.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>
</application>

5) Access the image file URI from MainActivity as

photoFile = File.createTempFile("new image", ".jpg", getExternalFilesDir(Environment.DIRECTORY_PICTURES)); 
Uri photoURI =  FileProvider.getUriForFile(this,"com.aravindsankaran.fileprovider",photoFile);

6) Pass this URI to intent before starting activity. This will make the camera app save the image under the provided URI.

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_FROM_DIR);

7) Passing the URI to image view

@Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            mImageView.setImageURI(photoURI);
         }

Capture Video

1) Same as above, except for the intent, use

MediaStore.ACTION_VIDEO_CAPTURE

2) Now, the intent returns the video URI as a part of the data. Set the URI on the videoView

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) {
        // this would return null for image intent
        Uri videoUri = intent.getData();
        mVideoView.setVideoURI(videoUri);
    }
}

3) Follow the same procedure as above to save the video under application content