Capturing Images with Mediastore.Action_Image_Capture Intent in Android

capturing images with MediaStore.ACTION_IMAGE_CAPTURE intent in android

Photos taken by the ACTION_IMAGE_CAPTURE are not registered in the MediaStore automatically on all devices.

The official Android guide gives that example:
http://developer.android.com/guide/topics/media/camera.html#intent-receive
But that does not work either on all devices.

The only reliable method I am aware of consists in saving the path to the picture in a local variable. Beware that your app may get killed while in background (while the camera app is running), so you must save the path during onSaveInstanceState.

Edit after comment:

Create a temporary file name where the photo will be stored when starting the intent.

File tempFile = File.createTempFile("my_app", ".jpg");
fileName = tempFile.getAbsolutePath();
Uri uri = Uri.fromFile(tempFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, PICTURE_REQUEST_CODE);

fileName is a String, a field of your activity. You must save it that way:

@Override
public void onSaveInstanceState(Bundle bundle)
{
super.onSaveInstanceState(bundle);
bundle.putString("fileName", fileName);
}

and recover it in onCreate():

public void onCreate(Bundle savedInstanceState)
{
if (savedInstanceState != null)
fileName = savedInstanceState.getString("fileName");
// ...
}

Now, at the time of onActivityResult, you know the name of the file where the photo was stored (fileName). You can do anything you wish with it, and then delete it.

2013-09-19 edit: It seems that some camera apps ignore the putExtra uri, and store the pic in a different place. So, before using the value of fileName you should check whether the intent is null or not. If you get a non-null intent, then you should prefer intent.getData() over fileName. Use fileName as a backup solution only when it is needed.

Capture Image from Camera and Display in Activity

Here's an example activity that will launch the camera app and then retrieve the image and display it.

package edu.gvsu.cis.masl.camerademo;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MyCameraActivity extends Activity
{
private static final int CAMERA_REQUEST = 1888;
private ImageView imageView;
private static final int MY_CAMERA_PERMISSION_CODE = 100;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.imageView = (ImageView)this.findViewById(R.id.imageView1);
Button photoButton = (Button) this.findViewById(R.id.button1);
photoButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE);
}
else
{
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
}
});
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MY_CAMERA_PERMISSION_CODE)
{
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(this, "camera permission granted", Toast.LENGTH_LONG).show();
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
else
{
Toast.makeText(this, "camera permission denied", Toast.LENGTH_LONG).show();
}
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK)
{
Bitmap photo = (Bitmap) data.getExtras().get("data");
imageView.setImageBitmap(photo);
}
}
}

Note that the camera app itself gives you the ability to review/retake the image, and once an image is accepted, the activity displays it.

Here is the layout that the above activity uses. It is simply a LinearLayout containing a Button with id button1 and an ImageView with id imageview1:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/photo"></Button>
<ImageView android:id="@+id/imageView1" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="wrap_content"></ImageView>

</LinearLayout>

And one final detail, be sure to add:

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

and if camera is optional to your app functionality. make sure to set require to false in the permission. like this

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

to your manifest.xml.

Returning an image to IMAGE_CAPTURE_INTENT

After research and experimenting, I have partially solved the problem. If I understood it correctly, there are two ways the IMAGE_CAPTURE_INTENT works:
If the ACTION_IMAGE_CAPTURE Intent contains EXTRA_OUTPUT, which is a Uri, you can save your taken image using this Uri to return an image. If there is no EXTRA_OUTPUT, the Intent for use with setResult() should contain a thumbnail-sized Bitmap in the _data extra. (Thanks @CommonsWare for the info!) I have only implemented the first option with the Uri, as I am still unsure how to do it with the thumbnail (most apps provide an Uri with their intent anyway).

The approach I took to return an image (only with Uri):

  1. Detect if the activity has been started due to an intent. Add the code below ideally in onResume, so the code checks for an intent every time the app is opened:
//check if activity was opened due to an intent
val isImageCaptureIntent = this.intent.action == MediaStore.ACTION_IMAGE_CAPTURE
if(isImageCaptureIntent) {
//retrieve the uri
val output = intent.extras?.get(MediaStore.EXTRA_OUTPUT)

//check if it is an Uri and not null
if (output != null && output is Uri) {
val uriImageCaptureIntent = output
isImageCaptureIntentWithUri = true
//an Uri is provided
}else{
isImageCaptureIntentWithUri = false
//an Uri is not provided, return a thumbnail-sized bitmap.
//I have not included a solution for this case!
}
}

  1. After the picture has been taken, save the image:
val imageOutStream: OutputStream
val contentResolver = context.contentResolver
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//use this approach to save the image with Android 10+ due to scoped storage

val mimeType = "image/jpeg"
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
put(MediaStore.Images.Media.MIME_TYPE, mimeType)
put(MediaStore.Images.Media.RELATIVE_PATH, directory)
}

contentResolver.run {
imageOutStream = openOutputStream(uriImageCaptureIntent) ?: return
}
}else{
//use this code for Android 9 and below
imageOutStream = context.contentResolver.openOutputStream(uriImageCaptureIntent)!!
}

try {
//bitmap equals the captured image
bitmap.compress(Bitmap.CompressFormat.JPEG, photoCompression, imageOutStream)
imageOutStream.flush()
} catch (e: java.lang.Exception) {
e.printStackTrace()
} finally {
imageOutStream.close()
}

  1. After storing the image, set result to OK and close the app:
 requireActivity().setResult(Activity.RESULT_OK, requireActivity().intent)
requireActivity().finish()

Update: Starting from Android 11, Android will no longer allow any third-party apps to capture an image via IMAGE_CAPTURE_INTENT. While the above code should work fine for Android 10 and below, starting form Android 11, no third-party apps will show up in the camera selection interface, when selecting an app to execute the capture intent.

Can an image taken with ACTION_IMAGE_CAPTURE intent be saved when system back button is pressed?

Sadly no, when you launch an intent to an external app you lose all the control you have and there is no way of changing it's behavior.
When the user press the back button from that intent, it will return to your app, but you will get the Activity.RESULT_CANCELED and no other information as you have already checked.

Your only option is to create your own camera activity instead of using the MediaStore.ACTION_IMAGE_CAPTURE one

camera captured image intent to other activity?

hi please try below code hope it will help you,

private final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
private final int MEDIA_TYPE_IMAGE = 1;

intent code for capture image

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
m_fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, m_fileUri);
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);

public Uri getOutputMediaFileUri(int p_type)
{
return Uri.fromFile(getOutputMediaFile(p_type));
}

private File getOutputMediaFile(int p_type)
{
File m_mediaFile;
if (p_type == MEDIA_TYPE_IMAGE)
{

m_buffer = new StringBuffer();

m_buffer.append(Environment.getExternalStorageDirectory().getPath() + File.separator).append("Image");
File m_imageStorageFile = new File(m_buffer.toString());

// Create the storage directory if it does not exist
if (!m_imageStorageFile.exists())
{
if (!m_imageStorageFile.mkdirs())
{
return null;
}
}
// Create a media file name
String m_timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new java.util.Date());
m_buffer = new StringBuffer();
m_buffer.append(m_imageStorageFile.getPath()).append(File.separator).append("IMG_").append(m_timeStamp).append(".jpg");
m_mediaFile = new File(m_buffer.toString());

}
else
{
return null;
}

return m_mediaFile;
}

write below code in your onActivityResult

protected void onActivityResult(int p_requestCode, int p_resultCode, Intent p_data)
{
super.onActivityResult(p_requestCode, p_resultCode, p_data);
if (p_resultCode == RESULT_OK)
{
switch (p_requestCode)
{
case CAMERA_CAPTURE_IMAGE_REQUEST_CODE:
m_selectedPath = m_fileUri.getPath();
break;

}
}
}

Constant.MEDIA_DIRECTORY_PATH contains your directory path
example :- mnt/sdcard0/android/com.example

Capture image in Android via intent (ACTION_IMAGE_CAPTURE)

If you want it to be 'secure', build camera functionality in your app. There is no way to be sure what some random camera app that comes pre-installed on a device does. They may be sending pictures to a server somewhere without you knowing. It's not super easy to do reliably, but you can only build the basic functionality. Failing that, require a specific app which you trust for image capture, by making the intent explicit (specify package name). This will, of course, require users to install it first if it is not already there.

Android continuous Image capture after saving first image (Intent - ACTION_IMAGE_CAPTURE)

Trigger the same intent again on activity result to start the camera again and handle it here only till when you want to capture the images.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE)
{
if (resultCode == RESULT_OK)
{
ImageView img=(ImageView)findViewById(R.id.imageView1);
img.setImageURI(fileUri);
Intent camIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(FileColumns.MEDIA_TYPE_IMAGE);
camIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(camIntent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}

else if (resultCode == RESULT_CANCELED)
{
}
}
}


Related Topics



Leave a reply



Submit