67

I am using intent to launch camera:

Intent cameraIntent = new Intent(
    android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
getParent().startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);

and using:

Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
photoImage.setImageBitmap(thumbnail);
photoImage.setVisibility(View.VISIBLE);

But it is only a thumbnail, how do I get the full bitmap? I know I can use my own Activity and use:

Camera.PictureCallback()

But is there anyway to do it using Intent?

Thanks!

edit:

I also tried:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    Uri uri = data.getData();
    imageView.setImageURI(uri);
}

It works for photo selected from gallery, but for camera intent, data.getData() returns null.

Heuristic
  • 5,087
  • 9
  • 54
  • 94

8 Answers8

110

To get full sized camera image you should point camera to save picture in temporary file, like:

    private URI mImageUri;

    Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
    File photo;
    try
    {
        // place where to store camera taken picture
        photo = this.createTemporaryFile("picture", ".jpg");
        photo.delete();
    }
    catch(Exception e)
    {
        Log.v(TAG, "Can't create file to take picture!");
        Toast.makeText(activity, "Please check SD card! Image shot is impossible!", 10000);
        return false;
    }
    mImageUri = Uri.fromFile(photo);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
    //start camera intent
    activity.startActivityForResult(this, intent, MenuShootImage);

private File createTemporaryFile(String part, String ext) throws Exception
{
    File tempDir= Environment.getExternalStorageDirectory();
    tempDir=new File(tempDir.getAbsolutePath()+"/.temp/");
    if(!tempDir.exists())
    {
        tempDir.mkdirs();
    }
    return File.createTempFile(part, ext, tempDir);
}

Then after image capture intent finished to work - just grab your picture from imageUri using following code:

public void grabImage(ImageView imageView)
{
    this.getContentResolver().notifyChange(mImageUri, null);
    ContentResolver cr = this.getContentResolver();
    Bitmap bitmap;
    try
    {
        bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, mImageUri);
        imageView.setImageBitmap(bitmap);
    }
    catch (Exception e)
    {
        Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "Failed to load", e);
    }
}


//called after camera intent finished
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    //MenuShootImage is user defined menu option to shoot image
    if(requestCode==MenuShootImage && resultCode==RESULT_OK) 
    {
       ImageView imageView;
       //... some code to inflate/create/find appropriate ImageView to place grabbed image
       this.grabImage(imageView);
    }
    super.onActivityResult(requestCode, resultCode, intent);
}

P.S. Code need to be revised with respect to new security restriction applied in Android M - FileProvider: mImageUri has to be packed with FileProvider

Barmaley
  • 16,638
  • 18
  • 73
  • 146
  • I tried it, the uri is file:///sdcard/.temp/picture19010.jpg and I used ImageView's setImageUri(), but it does not work, is the path correct, or do I need something to make the uri recognizable by imageview? – Heuristic Jun 23 '11 at 04:03
  • 1
    @barmaley I'm thankful you solved hzxu's problem, but I'm confused by your answer. That code doesn't work as-is. Any chance you can reformat and explain how 'grabImage' fits into the onActivityResult process? Thanks! – shanabus Jul 18 '11 at 03:46
  • @shanabus look more code above - I have added onActivityResult() – Barmaley Jul 18 '11 at 05:03
  • 5
    Just want to point out that the important line above is `intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);` see http://developer.android.com/reference/android/provider/MediaStore.html#ACTION_IMAGE_CAPTURE for the elusive documentation on this behavior. – Cheezmeister Jun 26 '12 at 14:59
  • @barmaley if i am saving the image permanently on the SD card. will i get the full sized image, or should i compulsorily use temp files? saving the image on the SD card is all that matters right, not whether its temp/permanent? – Archie.bpgc Sep 25 '12 at 11:53
  • Minor corrections for this line: `Toast.makeText(activity, "Please check SD card!...`. Toast does not take msecs parameter but rather a flag LENGTH_LONG or LENGTH_SHORT. Furthermore the ".show()" at the end is forgotten. Nothing very important but just to keep it clean. – George Pligoropoulos Feb 05 '13 at 21:32
  • 5
    I've tried this solution but the rsult of the image is an error like this: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=188, result=-1, data=null} to activity {com.ketanolab.lbc/com.ketanolab.lbc.Robototal}: java.lang.NullPointerException – Pedro Teran Nov 04 '13 at 19:50
  • What is MenuShootImage? – Mariana Hernandez May 12 '16 at 15:07
  • @MarianaHernandez `MenuShootImage` is requestcode this code will be returned in `onActivityResult()` when the activity exits. In this particular case some prefefined `int` which need to be `>0` – Barmaley May 12 '16 at 15:47
  • What about now with FileProvider?? Coz all this will not be working on Android 7 – Shikhar Mathur Aug 27 '16 at 17:39
  • It's amazing I've tried many solutions & only this worked for me! Thx! @ShikharMathur I just combined @barmaley's solution with this one (http://stackoverflow.com/a/38858040/1827488) to make `FileProvider` work. The config details for `FileProvider` in the docs are lacking & this post filled in the blanks which worked 1st try. You must check if `Build.VERSION.SDK_INT > M` when using `FileProvider.getUriForFile(...)` otherwise must continue to use `Uri.fromFile(...)` – rockhammer Feb 18 '17 at 05:17
  • Will the files remain in the temp directory? How do I delete them? – Sudhir Singh Khanger May 14 '17 at 18:16
  • Yes, file will remain in temp director, though it'll be invisible for gallery. To delete it, just delete directory: `Environment.getExternalStorageDirectory()+"/.temp/"` – Barmaley May 14 '17 at 18:34
  • I tried this and got android.os.FileUriExposedException. – Rohit May 18 '19 at 15:15
43

Open Camera and save image into some specific directory

private String pictureImagePath = "";
private void openBackCamera() {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = timeStamp + ".jpg";
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    pictureImagePath = storageDir.getAbsolutePath() + "/" + imageFileName;
    File file = new File(pictureImagePath);
    Uri outputFileUri = Uri.fromFile(file);
    Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);               
    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(cameraIntent, 1);
}

Handle Image

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 1) {
    File imgFile = new  File(pictureImagePath);
        if(imgFile.exists()){        
       Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
       ImageView myImage = (ImageView) findViewById(R.id.imageviewTest);
       myImage.setImageBitmap(myBitmap);

        }
    }

}
Vicky
  • 5,098
  • 2
  • 33
  • 31
  • 6
    After searching the internet for 24 hours, this was the only code that did what I want. The only problem now is, it is showing the image in landscape mode even if I take it in Portrait mode. – Srujan Barai Mar 20 '16 at 05:33
  • 7
    Also the only one that is working .....i really don't understand why such simple task should be so much complicated – Igor Vuković Oct 27 '16 at 08:23
  • 2
    Remember you need WRITE_EXTERNAL_STORAGE permission. The code in this answer is from https://developer.android.com/training/camera/photobasics.html – patraulea Feb 21 '17 at 20:41
  • 1
    Good one Simple and understandable.Others have done so much complicated codes – Hitesh Danidhariya Feb 23 '17 at 11:40
  • People really complicated the whole thing with long answers . One thing I'm facing after every click I come back to activity, can't I click multiple images together. can idea how to do? and thanks for this great code. – Panache Nov 04 '17 at 09:28
  • cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); this line prevents me to hit accept taken image button – Yaroslav Dukal Nov 14 '17 at 10:14
  • @MaksimKniazev I experience the same, it appears that for API > 24, we need to use getUriForFile as documented here: https://developer.android.com/training/camera/photobasics.html#TaskPath – Jens Nov 14 '17 at 12:37
  • Yeah, this worked by Android doc example which is similar does not. Thanks +1 – Wihan Fourie May 29 '18 at 07:22
  • Please update this, its always in landscape mode. Me and many others need a fix! – mathematics-and-caffeine Feb 25 '21 at 21:46
  • @LukasNiessen hi, have you resolved the issue with landscape mode? – Benazir Sh Mar 15 '22 at 19:35
6

Even though this is an old question and it has an accepted answer,
I would like to share my solution.
In this case you don't have to create a temporary file.
Additionally we creating a chooser which offers to user both: take a picture with the camera or pick an existing one from a gallery.

    Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    Intent chooser = new Intent(Intent.ACTION_CHOOSER);
    chooser.putExtra(Intent.EXTRA_INTENT, galleryIntent);
    chooser.putExtra(Intent.EXTRA_TITLE, getString(R.string.chooseaction));
    Intent[] intentArray = {cameraIntent};
    chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
    startActivityForResult(chooser, RESULT_LOAD_IMAGE);

and here we retrieving results:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // todo use appropriate resultCode in your case
    if (requestCode == RESULT_LOAD_IMAGE && resultCode == FragmentActivity.RESULT_OK) {
        if (data.getData() != null) {
            // this case will occur in case of picking image from the Gallery,
            // but not when taking picture with a camera
            try {
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), data.getData());

                // do whatever you want with the Bitmap ....           

            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            // this case will occur when taking a picture with a camera
            Bitmap bitmap = null;
            Cursor cursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    new String[]{MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_ADDED,
                            MediaStore.Images.ImageColumns.ORIENTATION}, MediaStore.Images.Media.DATE_ADDED,
                    null, "date_added DESC");
            if (cursor != null && cursor.moveToFirst()) {
                Uri uri = Uri.parse(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)));
                String photoPath = uri.toString();
                cursor.close();
                if (photoPath != null) {
                    bitmap = BitmapFactory.decodeFile(photoPath);
                }
            }

            if (bitmap == null) {
                // for safety reasons you can
                // use thumbnail if not retrieved full sized image
                bitmap = (Bitmap) data.getExtras().get("data");
            }
            // do whatever you want with the Bitmap ....
        }

        super.onActivityResult(requestCode, resultCode, data);
    }
}
Leo DroidCoder
  • 14,527
  • 4
  • 62
  • 54
  • really nice way, because it doesn't require readExternalStorage permission. Also native camera or gallery picker is comfortable way for user to complete action – Ragaisis Jul 19 '17 at 11:11
  • 3
    This and many other answers return last gallery image for camera instead of a camera shot. Tested in API 23 emulator and API 21 device. Uri references to a path different to an original photo. Also data == null. – CoolMind Feb 13 '18 at 16:14
  • Trying this out: If I select gallery everything works as described here. But if I select camera the resultCode == REQUEST_CANCELLED. – jwehrle Mar 09 '18 at 21:31
2

I also used the answer from Vicky but I had to save the uri to a bundle to avoid loss of it on orientation change. So if you don't get a result from your intent after tilting the device it might be because your uri did not survive the orientation change.

static final int CAMERA_CAPTURE_REQUEST = 1;
static final String ARG_CURRENT_PIC_URI = "CURRENT_PIC_URI";


String pictureImagePath = folderName + "/" + imageFileName;
File file = new File(Environment.getExternalStorageDirectory(), pictureImagePath);
Uri outputFileUri = Uri.fromFile(file);

mCurrentPicUri = outputFileUri.getPath();

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, CAMERA_CAPTURE_REQUEST);

Activity Result code:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

  if (requestCode == CAMERA_CAPTURE_REQUEST && resultCode == Activity.RESULT_OK) 
  {
    File imgFile = new  File(mCurrentPicUri);
    // do something with your image
    // delete uri
    mCurrentPicUri = "";
  }
}

save the uri to the bundle:

@Override
public void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  // save uri to bundle
  outState.putString(ARG_CURRENT_PIC_URI, mCurrentPicUri);
}

retrieve it from your saved bundle during on create:

if (bundle.containsKey(ARG_CURRENT_PIC_URI))
  mCurrentPicUri = bundle.getString(ARG_CURRENT_PIC_URI);
Mike Birkhoff
  • 505
  • 5
  • 10
2

Ok Time to pay back. So u have your permissions on Mainfest

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

and u also have your provider meta-data

 <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"></meta-data>
    </provider>

One missed detail is (android:authorities applicationId) u need to add your own app package name. So u have xml file under res folder as we mentioned on manifest and under it u have created file_paths with ;

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

we are done with copy paste part 1. Now on our activity above onCreate(savedInstanceState: Bundle?) define these beauties

    val REQUEST_IMAGE_CAPTURE = 1
    lateinit var currentPhotoPath: String
    var cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

U might like to have a look at original resource but missing details as usual Android Developers : link

An other missing detail is packageName + ".fileprovider", be carefull u need to give your own package name if u allredy have method.

// org android developers
    private fun dispatchTakePictureIntent() {
        Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
            // Ensure that there's a camera activity to handle the intent
            takePictureIntent.resolveActivity(packageManager)?.also {
                // Create the File where the photo should go
                val photoFile: File? = try {
                    createImageFile()
                } catch (ex: IOException) {
                    // Error occurred while creating the File
                    ex.message
                    null
                }
                // Continue only if the File was successfully created
                photoFile?.also {
                    val photoURI: Uri = FileProvider.getUriForFile(
                        this,
                        packageName + ".fileprovider",
                        it
                    )
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                    startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
                }
            }
        }
    }

createImageFile function

 // org android developers
    @Throws(IOException::class)
    private fun createImageFile(): File {
        // Create an image file name
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        val storageDir: File = this!!.getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!
        return File.createTempFile(
            "JPEG_${timeStamp}_", /* prefix */
            ".jpg", /* suffix */
            storageDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            currentPhotoPath = absolutePath
        }

    }

Testing. call your dispatchTakePictureIntent() method with onClick event, make sure permissions are permitted

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
  if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) {
var  mBitmap_org = MediaStore.Images.Media.getBitmap(
                this.getContentResolver(),
                //Uri.parse(currentPhotoPath)
                Uri.fromFile(File(currentPhotoPath))
            );
        //mImg_display?.setImageBitmap(mBitmap_org)
}
    }

Don't check data we will get it through imagePath. If u are checking Uri.parse(currentPhotoPath) make sure it's Uri.fromFile(File(currentPhotoPath))

Now u have your bitmap, time to spend other hours/days how to resize decode, save.

There is also a method to save tokken image, maybe you could help me to see where should I put it, if I need tokken image to be save on gallery

  // org android developers
    private fun galleryAddPic() {
        Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
            val f = File(currentPhotoPath)
            mediaScanIntent.data = Uri.fromFile(f)
            sendBroadcast(mediaScanIntent)
        }
    }
Samir
  • 6,405
  • 5
  • 39
  • 42
1

Don't use onActivityResult's data. It took me many hours to test different solutions. A camera saves a picture (even if you don't set permissions for camera and card reading in AndroidManifest), but then onActivityResult returns data == null and MediaStore returns wrong path. In these solutions you simply get last gallery image, not your photo.

private Uri photoUri;

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    ...
}

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

    if (requestCode == CAMERA_RESULT) {
        if (resultCode == RESULT_OK) {
            if (photoUri != null) {
                image.setImageURI(photoUri);
            }
        }
    }
}

private void showCamera() {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (intent.resolveActivity(getContext().getPackageManager()) != null) {
        File file = null;
        try {
            file = createImageFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        photoUri = null;
        if (file != null) {
            photoUri = Uri.fromFile(file);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
            startActivityForResult(intent, CAMERA_REQUEST);
        }
    }
}

private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File storageDir = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    // File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    return File.createTempFile(timeStamp, ".jpg", storageDir);
}
CoolMind
  • 26,736
  • 15
  • 188
  • 224
1

API Level 29

I tried the accepted answer, but both Environment.getExternalStorageDirectory() used in the accepted answer and Environment.getExternalStoragePublicDirectory() used in a subsequent answer are deprecated in API level 29. So is the MediaStore.Images.Media.DATA used in the third answer deprecated in API level 29. The following code (in Kotlin) stores the full image in MediaStore as shown in this stackoverflow answer to a different question and doesn't rely on the FileProvider:

    var imageUri: Uri? = null

    fun takePhoto(view: View?) {
        val values = ContentValues()
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, "myimage.jpg")
        values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
        values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
        imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)

        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
        startActivityForResult(intent, TAKE_PHOTO_REQUEST)
    }
Andy Hill
  • 136
  • 1
  • 11
  • But `MediaStore.MediaColumns.RELATIVE_PATH` deprecated too. – 林果皞 Dec 22 '22 at 08:05
  • Try `imageUri = contentResolver.insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ContentValues().apply { put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) }) ` This still works for me as of API Level 33. – Andy Hill Dec 23 '22 at 14:16
0

To capture maximum picture size from camera, i hope these simple steps will be quite useful

 public static Camera mCamera;

Camera.Parameters parameters = mCamera.getParameters();
  parameters.getSupportedPictureSizes();
List<Camera.Size> supportedSizes = parameters.getSupportedPictureSizes();
  mSizePicture1 = supportedSizes.get(0);
  int cameraSize = supportedSizes.size();
  mSizePicture2 = supportedSizes.get(cameraSize - 1);

    if (mSizePicture1.height < mSizePicture2.height)
       mSizePicture = supportedSizes.get(cameraSize - 1);
    else
       mSizePicture = supportedSizes.get(0);

parameters.setPictureSize(mSizePicture.width, mSizePicture.height);

Here, the supported size of the each mobile is taken, from that which size is maximum that is fixed as picture size to capture.

Gowthaman
  • 137
  • 1
  • 10