In my application ImageTakerActivity creates MediaStore.ACTION_IMAGE_CAPTURE intent to capture image.
I specified the following URI as MediaStore.EXTRA_OUTPUT. So its expected that ACTION_IMAGE_CAPTURE will write the taken photo to the corresponding file represented in the URI.
/******** ImageTakerActivity *********/
private void captureImage()
{
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
takePictureIntent.putExtra(MediaStore.EXTRA_FULL_SCREEN, true);
if (takePictureIntent.resolveActivity(getPackageManager()) != null)
{
startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_IMAGE);
}
}
public Uri getOutputMediaFileUri()
{
return Uri.fromFile(getOutputMediaFile());
}
private File getOutputMediaFile()
{
// External sdcard location
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),IMAGE_DIRECTORY_NAME);
//Deleting previous Images
if(mediaStorageDir.exists())
{
DeleteRecursive(mediaStorageDir);
}
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists())
{
if (!mediaStorageDir.mkdirs())
{
Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create " + IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmssSSS",Locale.getDefault()).format(new Date());
File mediaFile = new File(mediaStorageDir.getAbsolutePath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
In ActivityResult I did the following to retrieve the saved image:
private void decodeImageStream()
{
InputStream stream = null;
try
{
//this fileUri was passed to the takePictureIntent
stream = getContentResolver().openInputStream(fileUri);
image = BitmapFactory.decodeStream(stream);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
finally
{
if(stream != null)
{
try
{
stream.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}
Most of the time expected image is successfully decoded in image variable.
But sometimes after taking the picture when i tap OK, whole screen does a quick rotation and becomes black. After returning to onActivityResult of ImageTakerActivity, I get nothing in the image variable! Also there is no Exception on BitmapFactory.decodeStream too.
I have tried reading various articles available, but I don't know how to resolve the issue. Any help is very much appreciated!
Related
In my application, the code below enables the user to open the camera and take photo and save to Gallery, the code is working and the photo is saved to the gallery, but the problem is that the photo appears in the gallery rotated and in the end of the gallery with date equal to 1970, please can someone help me to fix these two problems? Thanks in advance. Below is my code:
code of capturing photo:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"myapplication.project",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_CAPTURE_TAG);
}
}
}
code of creating image file:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
method of saving photo to gallery:
public final void notifyMediaStoreScanner(final File file) {
try {
MediaStore.Images.Media.insertImage(getApplicationContext().getContentResolver(),
file.getAbsolutePath(), file.getName(), null);
getApplicationContext().sendBroadcast(new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
OnActivityResult method:
if (requestCode == CAMERA_CAPTURE_TAG && resultCode == Activity.RESULT_OK) {
//Bundle extras = data.getExtras();
//imageBitmap = (Bitmap) extras.get("data");
//imageSelected.setImageBitmap(imageBitmap);
File f =new File(currentPhotoPath);
notifyMediaStoreScanner(f);
}
Hi I am trying to make the images captured from my app inaccessible to the user. First I tried to save these images to internal storage which didnt work. Then I tried to hide them using "." infront of the folder name.I am not sure what the correct way to do this is. I also tried creating a file called .nomedia to bypass media scanner. I am very confused about the proper way to do this. Here's my code:
public String getImageUri(Context inContext, Bitmap inImage) {
/* *//* ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, ".title", null);
return Uri.parse(path);*//*
*/
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/.myFolder");
file.mkdirs();
File mFile = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/.nomedia");
mFile.mkdirs();
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(file);
inImage.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
fOut.flush();
fOut.close();
uri = MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return uri;
}
If I use file.mkdirs() I get filenotfoundexception. If i remove that line I get no errors but my uri is empty.
Does the above function return the file path as well? I need the file path and the uri later on. Any help is appreciated.
I guess you don't have to add another extension or something else just save them in external cache dir of your app and gallery app won't able to read your private directory until unless you notify about them.
so store your camera images here and no gallery app can detect it.
context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
sample code
public static File createPictureFile(Context context) throws IOException {
Locale locale = Locale.getDefault();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", locale).format(new Date());
String fileName = "JPEG_" + timeStamp + "_";
// Store in normal camera directory
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
return File.createTempFile(fileName, ".jpg", storageDir);
}
Save your image to internal storage instead. Other applications like MediaScanner or Gallery do not have permission to read from your own application memory. Sample code:
private String saveToInternalStorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"profile.jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
Save the image with different extension.
For example: .jpg can be saved as .ttj.
Try this code. Set where you want to save the photo. Once you receive response on onActivityResult(), in the desired URI, you will get the photo.
public void captureImageFromCamera() {
fileUri = FileUtils.getInstance().getOutputMediaFile(null);
if(fileUri == null){
Utilities.displayToastMessage(ApplicationNekt.getContext(),
context.getString(R.string.unable_to_access_image));
return;
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, TAKE_PICTURE);
}
Following function will give you desired path. Change it based on your project need.
public Uri getOutputMediaFile(String imageNameWithExtension) {
if (imageNameWithExtension == null)
imageNameWithExtension = "image_" + System.currentTimeMillis() + ".jpg";
String extPicDir = getExtDirPicturesPath();
if (!Utilities.isNullOrEmpty(extPicDir)) {
File mediaFile = new File(extPicDir, imageNameWithExtension);
return Uri.fromFile(mediaFile);
} else {
Log.d("tag", "getOutputMediaFile." +
"Empty external path received.");
return null;
}
}
public String getExtDirPicturesPath() {
File file = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (file != null)
return file.getPath();
else
Log.d("", "getExtDirPicturesPath failed. Storage state: "
+ Environment.getExternalStorageState());
return null;
}
To get the resultant photo.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK)
return;
switch (requestCode) {
case TAKE_PICTURE:
//fileuri variable has the path to your image.
break;
}
I got problem when playing with image, camera, and internal storage.
So I just about to change the code that I takes from google which has functionality to save image to sdcard. So I changed that code a little bit to this following codes...
public class CameraUtility {
private String currentPhotoPath;
private String imageCategoryName;
private ActionBarActivity activity;
private static final int REQUEST_TAKE_PHOTO = 1;
public CameraUtility(String imageCategoryName, ActionBarActivity activity){
this.imageCategoryName = imageCategoryName;
this.activity = activity;
}
public String getCurrentPhotoPath(){
return currentPhotoPath;
}
public String getImageCategoryName(){
return imageCategoryName;
}
public File createImageFile() throws IOException{
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = imageCategoryName + "_" + timeStamp + "_";
File localStorage = activity.getApplicationContext().getFilesDir();
/*
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, // prefix
".jpg", // suffix
localStorage // directory
);
*/
File image = new File(localStorage, imageFileName.concat(".jpg"));
if(!image.exists()){
image.createNewFile();
}
else{
image.delete();
image.createNewFile();
}
Log.d("LOCAL_STORAGE", localStorage.getAbsolutePath());
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = "file:" + image.getAbsolutePath();
return image;
}
public void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
Toast.makeText(activity.getApplicationContext(),
"Error occurred while creating the File",
Toast.LENGTH_SHORT).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Log.d("CAPTURED_AT", currentPhotoPath);
Toast.makeText(activity.getApplication().getApplicationContext(),
"Start Taking the Picture",
Toast.LENGTH_SHORT).show();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
activity.startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
else{
Toast.makeText(activity.getApplication().getApplicationContext(),
"File was not successfully created",
Toast.LENGTH_SHORT).show();
}
}
else{
Toast.makeText(activity.getApplication().getApplicationContext(),
"Activity package manager is null",
Toast.LENGTH_SHORT).show();
}
}
public void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(currentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
activity.sendBroadcast(mediaScanIntent);
}
}
As you can see, on createImageFile() method, there is some block code which have commented out, that section makes my code do save the image into external storage (sdcard).
So I want to change that code so that the camera activity save the captured image to internal storage by change that code to this one :
File image = new File(localStorage, imageFileName.concat(".jpg"));
if(!image.exists()){
image.createNewFile();
}
else{
image.delete();
image.createNewFile();
}
But when I try to confirm the image capture, the camera activity does not closed, just like in this picture...
That "check" icon button does not take any action when being pressed.
So what was happened in here?
Actually getExternalStoragePublicDirectoryis not getting the sdcard, but the primary memory that is shared among apps. So you can change it back to getExternalStoragePublicDirectory.
And also don't forget to change localStorage variable in commented code
When the user clicks the cross to not accept the photo, it ends the intent in the same way it does when they accept the photo they took. It saves a file to the device gallery. But it's blank. Shouldn't clicking the cross mean that resultCode != RESULT_OK? Is there one more check I am missing? Thanks. Here's the code. Wait, I'm saving the image before activity result...this is a flawed system, but it was on the official Android Developers website. If someone can suggest a fix I would be very greatful, because I used to save the image in onActivtyResult and it did not work on some phones, causing an exception, so I changed to this.
To start the intent:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
ih.galleryAddPic(mCurrentPhotoPath, this.getApplicationContext());
return image;
}
The camera intent case within onActivityResult:
else if ((requestCode == REQUEST_TAKE_PHOTO) && (resultcode == RESULT_OK)){
mProfilePicPath = mCurrentPhotoPath;
mPortraitPhoto = ih.decodeSampledBitmapFromImagePath(mCurrentPhotoPath,
GlobalConstants.PROFILE_PICTURE_RESOLUTION,
GlobalConstants.PROFILE_PICTURE_RESOLUTION);
TextView tv = (TextView) findViewById(id.ProfilePicText);
tv.setText(mProfilePicPath);
}
}catch(Exception ex){
Log.d("shkdghrfb", ex.toString());
}
}
EDIT: I changed onActivityResult to this, but to no avail (the blank image is still in my gallery afterwards, and the value of deleted is true):
else if (requestCode == REQUEST_TAKE_PHOTO){
if(resultcode == RESULT_OK){
File f = new File(mCurrentPhotoPath);
mProfilePicPath = null;
if (f.exists()) {
if (f.length() != 0){
mProfilePicPath = mCurrentPhotoPath;
mPortraitPhoto = ih.decodeSampledBitmapFromImagePath(mCurrentPhotoPath,
GlobalConstants.PROFILE_PICTURE_RESOLUTION,
GlobalConstants.PROFILE_PICTURE_RESOLUTION);
TextView tv = (TextView) findViewById(id.ProfilePicText);
tv.setText(mProfilePicPath);
}
else {
boolean deleted = f.delete();
if (deleted == true){
Log.d("camera0", "deleted");
}
else{
Log.d("camera0", "not deleted");
}
}
}
}
else{
File f = new File(mCurrentPhotoPath);
boolean deleted = f.delete();
if (deleted == true){
Log.d("camera", "deleted");
}
else{
Log.d("camera", "not deleted");
}
}
}
}catch(Exception ex){
Log.d("shkdghrfb", ex.toString());
}
}catch(Exception ex){
Log.d("shkdghrfb", ex.toString());
}
Edit Ok I believe I needed to scan the appropriate area of the SD card with a MediaScannerIntent after the delete, for it to show, as it seems to work now.
Aren't you creating file with createImageFile() ?
You may save photoFile and on result!=RESULT_OK delete it
By the way, camera apps(even default) may return wrong result. Check it in logs. If they do, just don't rely on result & check created file's size. If ==0 - delete it
Can anybody tell how to pass the captured image to a different activity to set the image view in android and store in a database? Can anybody provide code?
Thanks
Try this...
1.Capture and get the bitmap of the captured image in the onActivityResult()
public void capture(View view) {
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAPTURE_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == CAPTURE_REQUEST) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
}
}
}
2 Send the Image to the next Activity...You can send the Bitmap because it implements Parcelable
private void sendImage() {
Intent intent = new Intent(MainActivity.this, NextActivity.class);
intent.putExtra("image", thumbnail);
startActivity(intent);
}
3 Get the image in the NextActivity
Bundle extras = getIntent().getExtras();
if (extras != null) {
Bitmap image = (Bitmap) extras.get("image");
if (image != null) {
imageView.setImageBitmap(image);
}
}
you need to follow these steps :-
capture image using camera
save this image
get the file URI
In your next activity you can show this image using that file URI
let me know if you have any issue.
To Save your bitmap in sdcard use the following code
Store Image
private void storeImage(Bitmap image) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: ");// e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
image.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
To Get the Path for Image Storage
/** Create a File for saving an image or video */
private File getOutputMediaFile(){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/"
+ getApplicationContext().getPackageName()
+ "/Files");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
File mediaFile;
String mImageName="MI_"+ timeStamp +".jpg";
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
return mediaFile;
}