19

on click

 takePic.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                Intent m_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                imageUri = getImageUri();
                m_intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(m_intent, REQUEST_IMAGE_CAPTURE);
            }
        });

On Result:

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_IMAGE_CAPTURE
                    && resultCode == RESULT_OK) {   

                Log.d("test1",""+imageUri);
                Intent shareIntent = new Intent(this, SharePicForm.class);
                shareIntent.putExtra("photo",""+imageUri);
                startActivity(shareIntent);
            }

        }

getImageUri()

private Uri getImageUri(){
        Uri m_imgUri = null;
        File m_file;
        try {
            SimpleDateFormat m_sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
            m_curentDateandTime = m_sdf.format(new Date());
            m_imagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + m_curentDateandTime + ".jpg";
            m_file = new File(m_imagePath);
            m_imgUri = Uri.fromFile(m_file);
        } catch (Exception p_e) {
        }
        return m_imgUri;
    }

What I would like to achieve is very simple, call camera intent and get the uri of the result photo. But it seems there is an inconsistent of different device and on my device it isn't work at all. I tried to store the path on a public variable but when I retrieve it , it is null, is there formal and standard way to implement it and should be work on all device? Also, are there any way for not provide the custom path but get the default uri path from the camera intent ?

Thanks for helping

user782104
  • 13,233
  • 55
  • 172
  • 312

5 Answers5

14

If your device does not respect cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, you still can use

Uri imageUri = data.getData();

in onActivityResult(int requestCode, int resultCode, Intent data). But in most cases, the problem is that RAM is limited, and the system destroys your activity to give enough memory to the camera app to fulfill your intent. Therefore, when the result is returned, the fields of your activity are not initialized, and you should follow Amit's suggestion and implement onSavedInstance() and onRestoreInstanceState().

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 3
    data.getData returns null on most cases – zakjma Oct 01 '19 at 08:40
  • 1
    @zakjma: to receive `data.getData()`, you should not pass **MediaStore.EXTRA_OUTPUT** extra with your intent. – Alex Cohn Oct 02 '19 at 03:49
  • 3
    data.getData() returns null on my device(android 7.1.1) even if I dont pass MediaStore.EXTRA_OUTPUT with my intent. `Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, CAMERA_REQUEST_CODE);` – zakjma Oct 02 '19 at 07:45
  • @zakjma this could be buggy behaviour of your device, but it looks as if this `data.getData()` is no longer covered by the official docs. Note that they encourage you to use FileProvider instead of Uri, so this shift does make sense. – Alex Cohn Oct 02 '19 at 16:14
  • 1
    @zakjma Is right I dont get data.data even If dont pass MediaStore.EXTRA_OUTPUT – Sreekanth Karumanaghat Mar 17 '20 at 11:20
7

First of all make sure that your directory is created......

final String dir =  Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+ "/Folder/";
     File newdir = new File(dir); 
     newdir.mkdirs();

on button click call this function.

private void capturarFoto() {
 String file = dir+DateFormat.format("yyyy-MM-dd_hhmmss", new Date()).toString()+".jpg";


File newfile = new File(file);
            try {
                newfile.createNewFile();
            } catch (IOException e) {}       

            Uri outputFileUri = Uri.fromFile(newfile);

            Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);

            startActivityForResult(cameraIntent, TAKE_PHOTO_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == TAKE_PHOTO_CODE && resultCode == RESULT_OK) {
        Log.d("Demo Pic", "Picture is saved");


    }
}

Make sure You add permission in manifest

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

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
umair
  • 607
  • 4
  • 18
3

After a lot of research I found this solution. Just to make things clear I created an entire app for this question which serves the purpose of opening the camera clicking a photo and setting the image as the ImageBitmap of an ImageView. The code asked in this question starts at the second block i.e. the setView() method which is below the onCreate() method following which we have the onActivityResult() method

Here is a demo of the app.

Demonstration

Below I have Attached the MainActivity.java file

package com.cr7.opencamera;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    private Button buttonCaptureImageFromCamera;
    private Uri imageUri;
    private ImageView imageViewCameraImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Button that will open the camera
        buttonCaptureImageFromCamera = findViewById(R.id.buttonCaptureImageFromCamera);
        // ImageView that will store the image
        imageViewCameraImage = findViewById(R.id.imageViewCameraImage);
        askPermission();
    }

This what you need for geting the Uri of the image here imageUri is a global variable so that it can be used in the onActivityResult() method

    // Sets OnClickListener for the button if storage permission is given
    private void setView() {
        buttonCaptureImageFromCamera.setOnClickListener(v -> {
            String fileName = "new-photo-name.jpg";
            // Create parameters for Intent with filename
            ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.TITLE, fileName);
            values.put(MediaStore.Images.Media.DESCRIPTION, "Image capture by camera");
            imageUri =
                    getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                            values);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            startActivityForResult(intent, 1231);
        });
    }

This is the onActivityResult method. Here I've used imageUri i.e. the global variable of type Uri which was initialized in the OnClickListener of the button in the setView() method above.

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1231 && resultCode == Activity.RESULT_OK) {
            try {
                ContentResolver cr = getContentResolver();
                try {
                    // Creating a Bitmap with the image Captured
                    Bitmap bitmap = MediaStore.Images.Media.getBitmap(cr, imageUri);
                    // Setting the bitmap as the image of the
                    imageViewCameraImage.setImageBitmap(bitmap);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (IllegalArgumentException e) {
                if (e.getMessage() != null)
                    Log.e("Exception", e.getMessage());
                else
                    Log.e("Exception", "Exception");
                e.printStackTrace();
            }
        }
    }

Remaining code...


    // Asking user for storage permission
    public void askPermission() {
        // Checking if the permissions are not granted.
        if (
                ContextCompat.checkSelfPermission(
                        this,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE
                ) != PackageManager.PERMISSION_GRANTED ||
                        ContextCompat.checkSelfPermission(
                                this,
                                android.Manifest.permission.READ_EXTERNAL_STORAGE
                        ) != PackageManager.PERMISSION_GRANTED
        ) {
            // If not granted requesting Read and  Write storage
            ActivityCompat.requestPermissions(this, /*You can ask for multiple request by adding
            more permissions to the string*/new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
                            Manifest.permission.READ_EXTERNAL_STORAGE}, 60);
        } else {
            // If permissions are granted we proceed by setting an OnClickListener for the button
            // which helps the user pick the image
            setView();
        }
    }

    // This method is called after the permissions have been asked i.e. the dialog that says
    // allow or deny
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // Now by default we assume that the permission has not been granted
        boolean allPermissionsGranted = false;
        // Now we check if the permission was granted
        if ( requestCode == 60 && grantResults.length > 0) {
            // If all the permissions are granted allPermissionsGranted is set to true else false
            allPermissionsGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED
                    &&
                    grantResults[1] == PackageManager.PERMISSION_GRANTED;
        }
        // If permissions are granted we call the setView Method which prompts the user to pick
        // an Image either by the clicking it now or picking from the gallery
        if ( allPermissionsGranted ) {
            setView();
        }
    }
}

These blocks of code are in sequence i.e. if you merge all these blocks you get the complete MainActivity.java class.

If you wan to Implement this app you need yo create a layout file with an ImageView with an id "imageViewCameraImage"and a button with an id "buttonCaptureImageFromCamera".

Hope this helps. I know this is long and I'm making it longer by writing this. Regards, Joel

Joel
  • 353
  • 2
  • 7
2

To just get the thumbnail, you can use this:

val imageBitmap = data.extras.get("data") as Bitmap

To get the full picture:
See the specific steps from here (official docs)

You can read more from the docs.

Ahmed Ashour
  • 562
  • 5
  • 14
-9

simply use this Uri imageUri = data.getData();

Shoaib Anwar
  • 819
  • 2
  • 12
  • 29