I want to take a picture and store it in a folder with the name Medit via my app. When my app starts, it should be able to pull all the pictures from this folder and display it directly. So the data storage path must be set and stored as part of the app. Here is what I have done so far
public void CaptureImage(){
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mediaStorageDir =new File(Environment.getExternalStorageDirectory(),"MyAppName");
mUri =Uri.fromFile(mediaStorageDir+"IMG"+System.currentTimeMillis() + ".jpg");
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
super.onActivityResult(requestCode, resultCode, data);
Bitmap bm = BitmapFactory.decodeFile(mUri.getPath());
imgVIew.setImageBitmap(bm);
}else Log.d("capture", "FAILED");}
Issue is, irrespective what i change mUri to the picture is being stored in DCIM/ camera images with the default naming convention. In the onActivityResult I am capturing the image. Issue is Im not able to comtrol where it is being stored and as what name. I need to
1) Capture an image via intent, store it in a location with a custom name.
2) Everytime the app opens, it should go to that same storage location and pull out the pictures and display them one by one.
irrespective what i change mUri to the picture is being stored in DCIM/ camera images with the default naming convention
Most likely, that is a bug in that camera app. Most camera apps will honor EXTRA_OUTPUT properly. However, there is no enforcement mechanism to ensure that a camera app will honor EXTRA_OUTPUT.
However, please do not use string concatenation to create a file path, and make sure that you create your directories. IOW, replace:
mediaStorageDir =new File(Environment.getExternalStorageDirectory(),"MyAppName");
mUri =Uri.fromFile(mediaStorageDir+"IMG"+System.currentTimeMillis() + ".jpg");
with:
mediaStorageDir=new File(Environment.getExternalStorageDirectory(),"MyAppName");
mediaStorageDir.mkdirs();
mUri=Uri.fromFile(new File(mediaStorageDir, "IMG"+System.currentTimeMillis() + ".jpg"));
It is possible that changing this code will make your app more compatible with this particular camera app, but there are no guarantees that all camera apps will behave as you wish.
I need to...
Your code is written to give you what you want. However, you are invoking a third-party app with the ACTION_IMAGE_CAPTURE Intent. There are thousands of camera apps, both pre-installed and available for download from the Play Store and elsewhere. Many will have properly-working ACTION_IMAGE_CAPTURE implementations. Some will not.
Either:
Detect that the image is not at your desired path and let the user know that their camera app is broken. Then, suggest that they install some third-party camera app that you have tested. Or,
Stop using ACTION_IMAGE_CAPTURE and work with the camera APIs directly, though this is rather difficult.
Your pictures are being save in default path because the path you are providing is wrong. Use the following code.
File mediaStorageDir =new File(Environment.getExternalStorageDirectory(),"MyAppName");
if(!mediaStorageDir.exists())
mediaStorageDir.mkdir();
Uri mUri = Uri.fromFile(new File(mediaStorageDir.getAbsolutePath() + "/IMG" + System.currentTimeMillis() + ".jpg"));
LogHelper.LogI("path", mUri.getPath());
Please try th following code it's working for me.
public class CaptureImage extends Activity {
private static final int PICK_CAMERA_IMAGE = 2;
ImageView img;
Button btn;
private Uri mImageCaptureUri;
public static String userPicPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_capture_image);
img = (ImageView) findViewById(R.id.activity_capture_image_img);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(
"yyyyMMdd_HHmmss", Locale.US);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(Environment.getExternalStorageDirectory()
+ "/" + Constants.IMAGE_DIRECTORY_NAME, "img_"
+ dateFormatter.format(new Date()).toString() + ".png");
userPicPath = file.getPath();
mImageCaptureUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
startActivityForResult(intent, PICK_CAMERA_IMAGE);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_CAMERA_IMAGE && resultCode == RESULT_OK) {
Log.d("CaptureImage", mImageCaptureUri.toString());
Bitmap bitmapProfile = getBitmap(userPicPath, this);
img.setImageBitmap(bitmapProfile);
}
}
public static Bitmap getBitmap(String path, Context context) {
Uri uri = Uri.fromFile(new File(path));
InputStream in = null;
ContentResolver mContentResolver = context.getContentResolver();
try {
// final int IMAGE_MAX_SIZE = 2048;
final int IMAGE_MAX_SIZE = 1024;
in = mContentResolver.openInputStream(uri);
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, o);
in.close();
int scale = 1;
if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
scale = (int) Math.pow(
2,
(int) Math.round(Math.log(IMAGE_MAX_SIZE
/ (double) Math.max(o.outHeight, o.outWidth))
/ Math.log(0.5)));
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
in = mContentResolver.openInputStream(uri);
Bitmap b = BitmapFactory.decodeStream(in, null, o2);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG, 25, stream);
in.close();
return b;
} catch (FileNotFoundException e) {
Log.e("CaptureImage", "file " + path + " not found");
} catch (IOException e) {
Log.e("CaptureImage", "file " + path + " not found");
}
return null;
}
}
Related
I'm fairly new to android development and I'm trying to create an app that calls implicit intent for the camera by clicking one button. Once the image is captured you can click back button to get to main activity. In the main activity there's second button that when you click it you can see recent files and the captured image should be showing there
I was working through https://developer.android.com/training/camera/photobasics.html#TaskScalePhoto
Used the following code for capturing the image
final TextView textviewcamera = (TextView) findViewById(R.id.TextView1);
final int REQUEST_IMAGE_CAPTURE = 1;
// Set an OnClickListener on this Text View
// Called each time the user clicks the Text View
textviewcamera.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
/*
opens the camera app and we are able to take a photo, photo is not save anywhere, needs to be fixed
code is from android studio, DON'T FORGET to cite
https://developer.android.com/training/camera/photobasics.html
*/
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//if (takePictureIntent.resolveActivity(getPackageManager()) != null)
//{
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
//}
}
Then I have another piece of code that shows the recent files
final TextView textviewpicture = (TextView) findViewById(R.id.TextView2);
// Set an OnClickListener on this Text View
// Called each time the user clicks the Text View
textviewpicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*
opens the camera app and we are able to take a photo, photo is not save anywhere, needs to be fixed
code is from android studio, DON'T FORGET to cite
https://developer.android.com/training/camera/photobasics.html
*/
Intent viewpicture = new Intent();
viewpicture.setType("image/*");
viewpicture.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(viewpicture, "Select Picture"), 10);
}
});
I'm able to open the camera and take the photo however when I try to view it in my recent files, this part is not working.
Any help would be highly appreciated
Thanks a mill everyone :)
override your onActivityresult there you can preview your image from there save it to external storage
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_IMAGE_CAPTURE:
if (resultCode != RESULT_CANCELED)
{
if (resultCode == RESULT_OK) {
BitmapFactory.Options options = new
BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
options);
saveImageToExternalStorage(bitmap)
}
} else{
//show error message
}
} }
public static File saveImageToExternalStorage(Bitmap finalBitmap) {
File file;
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myDir = new File(root + "/easyGovs");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".png";
file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.PNG, 55, out);
out.flush();
out.close();
return file;
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
and while passing your intent for camera use this -
private Uri fileUri;
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
My app is crashing after capturing 5 to 6 photos using intents.log cat shows nothing. am unable to find the reason why it is crashing. please help me out.
private void capturePhoto() {
File root = new File(Environment.getExternalStorageDirectory(), "Feedback");
if (!root.exists()) {
root.mkdirs();
}
File file = new File(root, Constants.PROFILE_IMAGE_NAME + ".jpeg");
Uri outputFileUri = Uri.fromFile(file);
Intent photoPickerIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
photoPickerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
photoPickerIntent.putExtra("return-data", true);
photoPickerIntent.putExtra("android.intent.extras.CAMERA_FACING", 1);
startActivityForResult(photoPickerIntent, requestCode);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (this.requestCode == requestCode && resultCode == RESULT_OK) {
File root = new File(Environment.getExternalStorageDirectory(), "Feedback");
if (!root.exists()) {
root.mkdirs();
}
File file = new File(root, Constants.PROFILE_IMAGE_NAME+".jpeg");
checkFlowIdisPresent(file);
displayPic();
}
}
private void displayPic() {
String filePath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator + "/Feedback/" + Constants.PROFILE_IMAGE_NAME + ".jpeg";
// Bitmap bmp = BitmapFactory.decodeFile(filePath);
//Bitmap scaled = Bitmap.createScaledBitmap(bmp, 300, 300, true);
File imgFile = new File(filePath);
Bitmap bmp = decodeFile(imgFile);
if (imgFile.exists()) {
dispProfilePic.setImageBitmap(bmp);
} else {
dispProfilePic.setBackgroundResource(R.drawable.user_image);
}
}
private Bitmap decodeFile(File f) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 70;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE &&
o.outHeight / scale / 2 >= REQUIRED_SIZE) {
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
}
return null;
}
And above code is for capturing photo and displaying captured picture in ImageView. And am using MI tab.
Edit actually app is not crashing...it becomes white screen and if i press any button then it is crashing and onActivityResult is not executed when it become white screen
New Edit Am able to replicate this. I clicked on Android Monitor in that i clicked Monitor. Then it shows memory utilization of the app when i interacting with app. now in left side bar i clicked terminate application icon. Now the interesting thing is it destroys current activity and moves to previous activity. That previous activity become white screen.
Please help me out guys.
Try this code. I use it in some of my apps :
Launch intent method:
private void launchCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
}
Capturing result:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (requestCode == CAMERA_PIC_REQUEST) {
if (data != null) {
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap thumbnail = (Bitmap) extras.get("data");
if (thumbnail != null)
displayPic(thumbnail);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Well your code fine....
I think you save the image or overwrite image on same path with same name so there is problem with memory. So I recommended you change the name with System.currentTimeMillis() or any random name Instead of Constants.PROFILE_IMAGE_NAME.
And Also check the permission
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Also check this permission with run time also...for run time follow this
private static final int REQUEST_RUNTIME_PERMISSION = 123;
if (CheckPermission(demo.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
capturePhoto();
} else {
// you do not have permission go request runtime permissions
RequestPermission(demo.this, Manifest.permission.WRITE_EXTERNAL_STORAGE, REQUEST_RUNTIME_PERMISSION);
}
public void RequestPermission(Activity thisActivity, String Permission, int Code) {
if (ContextCompat.checkSelfPermission(thisActivity,
Permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Permission)) {
capturePhoto();
} else {
ActivityCompat.requestPermissions(thisActivity,
new String[]{Permission},
Code);
}
}
}
public boolean CheckPermission(Activity context, String Permission) {
if (ContextCompat.checkSelfPermission(context,
Permission) == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
If nothing is displayed on the log cat it is very difficult to speculate anything but please check whether the problem is when using the emulator and not on a real device. You can also check if you can recreate the problem by making the emulator capacity smaller (Ram and internal memory). If that is the case, then increase the memory or ram of your emulator and it should work fine. You then need to work on optimizing you image processing task for lower spec devices.
Hope this helps.
This happens possibly because the Calling Activity gets killed and then restarted by OS as IMAGE CAPTURE intent deals with huge amount of memory for processing the BITMAP captured via CAMERA.
Solution: Save the file path of the Image and use it when onActivityResult is called. You can use onSavedInstanceState and onRestoreInstanceState methods to save and retrieve the IMAGE_PATH and other fields of the activity.
You can refer to this link for how to use onSavedInstanceState and onRestoreInstanceState
Try doing it in an Async task because the issue u facing is due to the hug processing done in UI thread
refer here for more help on Async task implementation
This may be memory problem you are taking photos and storing them in bitmap
Check your android Monitor for Memory Detection of APp
Just make this method static
private static Bitmap decodeFile(File f) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 70;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE &&
o.outHeight / scale / 2 >= REQUIRED_SIZE) {
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
}
return null;
}
Save files with different names like saving with timestamp as name
Try to use below code. It works fine for me.
private static final int REQUEST_CAMERA = 1;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
{
if (requestCode == REQUEST_CAMERA)
{
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File destination = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".jpg");
FileOutputStream fos;
try
{
destination.createNewFile();
fos = new FileOutputStream(destination);
fos.write(bytes.toByteArray());
fos.close();
}
catch (FileNotFoundException fnfe)
{
fnfe.printStackTrace();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
ivSetImage.setImageBitmap(thumbnail);
}
}
}
In the given code snippet, I have compressed the captured image, due to which app crashing problem is resolved.
In your case, the captured image quality might be high due to which your app is crashing while setting up an image on ImageView.
Just try compressing an image. It will work!
Don't forget to add permission in manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
check your Manifast.xml file permission
External Storage
and Camera permission.
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" /> <uses-feature
android:name="android.hardware.camera.autofocus" />
if your App run on Marshenter code heremallow check run time permission
Try to use below code:
private void launchCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (requestCode == CAMERA_PIC_REQUEST) {
if (data != null) {
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap thumbnail = (Bitmap) extras.get("data");
if (thumbnail != null)
displayPic(thumbnail);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
I have to launch the camera, and when the users has done the picture, I have to take it and show it in a view.
Looking at http://developer.android.com/guide/topics/media/camera.html I have done:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bLaunchCamera = (Button) findViewById(R.id.launchCamera);
bLaunchCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "lanzando camara");
//create intent to launch camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); //create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //set the image file name
//start camera
startActivityForResult(intent, CAMERA_REQUEST);
}
});
/**
* Create a File Uri for saving image (can be sued to save video to)
**/
private Uri getOutputMediaFileUri(int mediaTypeImage) {
return Uri.fromFile(getOutputMediaFile(mediaTypeImage));
}
/**
* Create a File for saving image (can be sued to save video to)
**/
private File getOutputMediaFile(int mediaType) {
//To be safe, is necessary to check if SDCard is mounted
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
(String) getResources().getText(R.string.app_name));
//create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(TAG, "failed to create directory");
return null;
}
}
//Create a media file name
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date());
File mediaFile;
if (mediaType == 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) {
if(resultCode == RESULT_OK) {
//Image captured and saved to fileUri specified in Intent
Toast.makeText(this, "image saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();
Log.d(TAG, "lanzando camara");
} else if(resultCode == RESULT_CANCELED) {
//user cancelled the image capture;
Log.d(TAG, "usuario a cancelado la captura");
} else {
//image capture failed, advise user;
Log.d(TAG, "algo a fallado");
}
}
}
When the picture has been done, the app crashes when it try to send the 'Toast' info because 'data' is null.
But if I debug the app I can see that the image has been saved.
So my question is: How can I get the path in the onActivityResult?
The problem you are facing is that, whenever we select an image from camera intent, it may finish the activity which called it, so imageUri object you created will be null while you return.
so you need to save it when you exit the activity (to go to camera intent), like this -
/**
* Here we store the file url as it will be null after returning from camera
* app
*/
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save file url in bundle as it will be null on screen orientation
// changes
outState.putParcelable("file_uri", mImageUri);
}
and retrieve it back when you come back to the activity -
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// get the file url
mImageUri = savedInstanceState.getParcelable("file_uri");
}
Your code looks fine, you only need to add this change in it.
Here is code I have used for Capturing and Saving Camera Image then display it to imageview. You can use according to your need.
You have to save Camera image to specific location then fetch from that location then convert it to byte-array.
Here is method for opening capturing camera image activity.
private static final int CAMERA_PHOTO = 111;
private Uri imageToUploadUri;
private void captureCameraImage() {
Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(Environment.getExternalStorageDirectory(), "POST_IMAGE.jpg");
chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
imageToUploadUri = Uri.fromFile(f);
startActivityForResult(chooserIntent, CAMERA_PHOTO);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_PHOTO && resultCode == Activity.RESULT_OK) {
if(imageToUploadUri != null){
Uri selectedImage = imageToUploadUri;
getContentResolver().notifyChange(selectedImage, null);
Bitmap reducedSizeBitmap = getBitmap(imageToUploadUri.getPath());
if(reducedSizeBitmap != null){
ImgPhoto.setImageBitmap(reducedSizeBitmap);
Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton);
uploadImageButton.setVisibility(View.VISIBLE);
}else{
Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
}
}
}
Here is getBitmap() method used in onActivityResult(). I have done all performance improvement that can be possible while getting camera capture image bitmap.
private Bitmap getBitmap(String path) {
Uri uri = Uri.fromFile(new File(path));
InputStream in = null;
try {
final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
in = getContentResolver().openInputStream(uri);
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, o);
in.close();
int scale = 1;
while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) >
IMAGE_MAX_SIZE) {
scale++;
}
Log.d("", "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight);
Bitmap b = null;
in = getContentResolver().openInputStream(uri);
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
o = new BitmapFactory.Options();
o.inSampleSize = scale;
b = BitmapFactory.decodeStream(in, null, o);
// resize to desired dimensions
int height = b.getHeight();
int width = b.getWidth();
Log.d("", "1th scale operation dimenions - width: " + width + ", height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,
(int) y, true);
b.recycle();
b = scaledBitmap;
System.gc();
} else {
b = BitmapFactory.decodeStream(in);
}
in.close();
Log.d("", "bitmap size - width: " + b.getWidth() + ", height: " +
b.getHeight());
return b;
} catch (IOException e) {
Log.e("", e.getMessage(), e);
return null;
}
}
I hope it helps!
In my app i'm using the camera app on the phone in order to take a picture. After taking the picture it returns back to my app. I noticed that it acts differently in different phones. In Galaxy s3 I found that after taking a picture it shows the picture and gives an option to save it (and then go back to my app) or discard (and go back to the camera app). The problem is that when the screen is rotated the app crushes when the save/discard screen appears. The only way to stop it from crushing is to take the picture without rotating the screen and keep it that way.
Is there a solution to this problem? Maybe there is a way that I can define that it won't allow rotation at this screen?
Here is the code:
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
//Specify target file
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
newPicName = android.os.Environment.getExternalStorageDirectory() + "/"+app.APP_FOLDER + "/" + app.getSession()+ "_"+app.getDateTime()+ "_" +sdf.format(cal.getTime()) +".jpg";
File imageFile = new File(newPicName);
Uri imageFileUri = Uri.fromFile(imageFile);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageFileUri);
startActivityForResult(intent, 0);
If you just want to limit the orientation of the screen you need to specify it in your manifest… For example:
<activity
android:name="com.xxx"
android:label="#string/xxx"
android:screenOrientation="portrait" > //this limits the screen to only portrait.
</activity>
Additional Info
This is how I do it and it works for me perfectly.
//instance variables
private static final int TAKE_PICTURE = 0;
private Uri mUri;
private Bitmap mPhoto;
//First I create a method to capture the image.
private void captureImage() {
Intent i = new Intent("android.media.action.IMAGE_CAPTURE");
File f = new File(Environment.getExternalStorageDirectory(), "profile.jpg");
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
mUri = Uri.fromFile(f);
startActivityForResult(i, TAKE_PICTURE);
}
//Then I handle the result.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PICTURE://this is a constant defined in my instance variables.
if (resultCode == Activity.RESULT_OK) {
getContentResolver().notifyChange(mUri, null);
ContentResolver cr = getContentResolver();
try {
mPhoto = android.provider.MediaStore.Images.Media.getBitmap(cr, mUri);
//set your photo in a screen…
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
}
Try following code :
private File tempFile;
private static final int CAMERA_IMAGE = 1;
public void takePicFromCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (tempFile != null) {
Log.i(""image Path : "", tempFile.getPath());
Uri picUri = Uri.fromFile(tempFile); // convert path to Uri
intent.putExtra(MediaStore.EXTRA_OUTPUT, picUri);
Log.i("Picture Uri", " : " + picUri);
}
startActivityForResult(intent, MedicationConstants.CAMERA_IMAGE);
}
public void onActivityResult(int requestCode, int resultCode, final Intent intent) {
if (requestCode == MedicationConstants.CAMERA_IMAGE) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (tempFile != null) {
//do anything with image file. Store in database. Or even should add functionality of dropping
}
}
}, 2000);
}
}
In on onActivityResult you should add functionality of image cropping. Please have a look at simple-crop-image-lib. It is great library & works for almost all device.
Thanks
I am trying to get the full image after taking a picture from a Fragment.
If I use the Uri from the file (Uri.fromFile(file)), the camera won't exit after taking the photo and tapping on the 'ok' button (looks like can't write to the Uri or who knows what).
Using the File String, in the form of '/data/data/com.package.bla/cache/img198346262jpg', it's not working as well (The file is there, but it's empty because the camera is not saving anything on it).
What I tried so far:
Deleting the file after creating it, as this example does. However, the file doesn't exist after the camera exits.
Added External Storage READ permission, just in case
So I have no idea why the image is not being saved and already spent/wasted a lot of time testing and figuring why it's not working.
Fragment:
private void launchCamera() {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File outputDir = getActivity().getCacheDir();
File file = null;
try {
file = File.createTempFile("img", "jpg", outputDir);
} catch (IOException e) {
e.printStackTrace();
}
if (file != null) {
mImageUri = Uri.fromFile(file); //using Uri is not even exiting the camera
//mImageUri = File.toString(); //If I use String instead of an Uri, it works better (ie, can accept camera photo)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(cameraIntent, RESULT_TAKE_IMAGE);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
Bitmap original = BitmapFactory.decodeFile(mImageUri.toString(), bounds);
}
}
Edited code, mImageUri. As explained, if I use Uri I can't even accept the photo in the camera app. Using a String will let me accept the photo, though the photo is not actually saved (ie the file has 0 bytes inside it).
EXPLANATION: The problem was related to saving into the cache directory. Maybe it's a bug, I am missing a permission or the camera app just can't save into your application private data directory. Adding Permission FLAG_GRANT_WRITE_URI_PERMISSION didn't solve it. Related posts: Store image from camera into private app cache directory AND Saving camera data to cache when launched via intent
UPDATE From Android 2.2 onwards getExternalCacheDir() method can be used instead of getCacheDir()
from android 26+ Uri.fromFile will not work, you should use File provider instead.
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
.........
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
</application>
res/xml/file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
</paths>
finally
final Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
// output file
File path = new File(Environment.getExternalStorageDirectory(), "tmp.mp4");
// com.mydomain.fileprovider is authorities (manifest)
// getUri from file
Uri uri = FileProvider.getUriForFile(this, "com.mydomain.fileprovider", path);
takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(takeVideoIntent, 99);
tested on android 8.0 and 5.1.1
Update: on some device built-in camera would not support for EXTRA_OUTPUT, so if you want to work on all devices, build your own camera module.
Why not saving it in a new File
final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "MyDir" + File.separator);
root.mkdirs();
final String fname = "img_"+ System.currentTimeMillis() + ".jpg";
final File sdImageMainDirectory = new File(root, fname);
mImageUri = Uri.fromFile(sdImageMainDirectory);
And then pass that uri to the intent
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
Try this is working like charm with me
private String selectedImagePath = "";
final private int PICK_IMAGE = 1;
final private int CAPTURE_IMAGE = 2;
public Uri setImageUri() {
// Store image in dcim
File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/", "image" + new Date().getTime() + ".png");
Uri imgUri = Uri.fromFile(file);
this.imgPath = file.getAbsolutePath();
return imgUri;
}
public String getImagePath() {
return imgPath;
}
btnGallery.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, ""), PICK_IMAGE);
}
});
btnCapture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, setImageUri());
startActivityForResult(intent, CAPTURE_IMAGE);
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_CANCELED) {
if (requestCode == PICK_IMAGE) {
selectedImagePath = getAbsolutePath(data.getData());
imgUser.setImageBitmap(decodeFile(selectedImagePath));
} else if (requestCode == CAPTURE_IMAGE) {
selectedImagePath = getImagePath();
imgUser.setImageBitmap(decodeFile(selectedImagePath));
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
public Bitmap decodeFile(String path) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 70;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeFile(path, o2);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
public String getAbsolutePath(Uri uri) {
String[] projection = { MediaColumns.DATA };
#SuppressWarnings("deprecation")
Cursor cursor = managedQuery(uri, projection, null, null, null);
if (cursor != null) {
int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} else
return null;
}