Reputation: 482
Google offers this versatile code for taking photos via an intent:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// create Intent to take a picture and return control to the calling application
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
// start the image capture Intent
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
The problem is that if you're like me and you want to pass the photos as extras, using EXTRA_OUTPUT
seemingly runs off with the photo data and makes subsequent actions think the intent data is null.
It appears this is a big bug with Android.
I'm trying to take a photo then display it as a thumbnail in a new view. I'd like to have it saved as a full sized image in the user's gallery. Does anyone know a way to specify the image location without using EXTRA_OUTPUT
?
Here's what I have currently:
public void takePhoto(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
// takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
@SuppressLint("SimpleDateFormat")
private static File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "JoshuaTree");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("JoshuaTree", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
handleSmallCameraPhoto(data);
}
}
}
private void handleSmallCameraPhoto(Intent intent) {
Bundle extras = intent.getExtras();
mImageBitmap = (Bitmap) extras.get("data");
Intent displayIntent = new Intent(this, DisplayPhotoActivity.class);
displayIntent.putExtra("BitmapImage", mImageBitmap);
startActivity(displayIntent);
}
}
Upvotes: 18
Views: 45363
Reputation: 492
Basically, there are two ways to retrieve the image from Camera, if you use to send a captured image through intent extras you cannot retrieve it on ActivityResult on intent.getData() ' because it saves the image data through extras.
So the idea is:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
And retrieving it on ActivityResults checking the retrieved intent:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == RESULT_OK) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (intent.getData() != null) {
ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(intent.getData(), "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
} else {
Bitmap imageRetrieved = (Bitmap) intent.getExtras().get("data");
}
}
}
}
Upvotes: 1
Reputation: 1380
Try this one android.provider.MediaStore.EXTRA_OUTPUT
hope will solve your bug. The following code works for me:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
I was facing same problem, every time getting null while retrieving data on other activity with getIntent().getData()
then solved by writting complete android.provider.MediaStore.EXTRA_OUTPUT
this solved my bug.
Upvotes: 0
Reputation: 2960
Here is how you can achieve what you want:
public void onClick(View v)
{
switch(v.getId())
{
case R.id.iBCamera:
File image = new File(appFolderCheckandCreate(), "img" + getTimeStamp() + ".jpg");
Uri uriSavedImage = Uri.fromFile(image);
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
i.putExtra("return-data", true);
startActivityForResult(i, CAMERA_RESULT);
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case CAMERA_RESULT:
if(resultCode==RESULT_OK)
{
handleSmallCameraPhoto(uriSavedImage);
}
break;
}
}
private void handleSmallCameraPhoto(Uri uri)
{
Bitmap bmp=null;
try {
bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
Intent displayIntent = new Intent(this, DisplayPhotoActivity.class);
displayIntent.putExtra("BitmapImage", bmp);
startActivity(displayIntent);
}
private String appFolderCheckandCreate(){
String appFolderPath="";
File externalStorage = Environment.getExternalStorageDirectory();
if (externalStorage.canWrite())
{
appFolderPath = externalStorage.getAbsolutePath() + "/MyApp";
File dir = new File(appFolderPath);
if (!dir.exists())
{
dir.mkdirs();
}
}
else
{
showToast(" Storage media not found or is full ! ");
}
return appFolderPath;
}
private String getTimeStamp() {
final long timestamp = new Date().getTime();
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timestamp);
final String timeString = new SimpleDateFormat("HH_mm_ss_SSS").format(cal.getTime());
return timeString;
}
Edit:
Add these to Manifest:
Starting Api 19 and above READ_EXTERNAL_STORAGE should be declared explicitly
*<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />*
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
to you manifest.
Upvotes: 0
Reputation: 366
If you specified MediaStore.EXTRA_OUTPUT, the image taken will be written to that path, and no data will given to onActivityResult. You can read the image from what you specified.
See another solved same question here: Android Camera : data intent returns null
Upvotes: 19