Sorry to bother you guys, but I am not able to get a solution where In we take picture using intents. I know the default behavior of native camera is to save the picture at default directory/place of O.S. The thing is I have some requirements where I do not want to save the picture when clicked using camera app. There has to be a solution of this issue, be it like once we take a picture we could delete it right away, or there should be an alternate by which we won't allow O.S to save Image, please help.
Here is a piece of code I tried, tried several ways by creating a directory and then deleting file, nothing works.
public void takeImageFromCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check for the integer request code originally supplied to startResolutionForResult().
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
if (isCameraPermissionGranted()) {
bitmap= (Bitmap) data.getExtras().get("data");
// bitmap = processReuiredImage(picUri);
getProfileDetailViaFace(encodeImageBitmapToString(bitmap));
Log.d("path",String.valueOf(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES)));
// getApplicationContext().getContentResolver().delete(, "/storage/emulated/0/Pictures", null);
// mediaStorageDir.getPath().delete();
} else {
requestCameraPermission();
}
}
public void takeImageFromCamera() {
File file = getOutputMediaFile(CAMERA_FILE_TYPE);
if (Build.VERSION.SDK_INT >= 24) {
try {
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
}
picUri = Uri.fromFile(file);
Intent takePictureIntent = new
Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, picUri);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, CAMERA_REQUEST);
}
}
private File getOutputMediaFile(int type) {
mediaStorageDir = new
File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "peppercard");
/**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("yyyyMMdd_HHmmss").format(new Date());
if (type == CAMERA_FILE_TYPE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpeg");
} else {
return null;
}
}
return mediaFile;
}
The thing is I have some requirements where I do not want to save the picture when clicked using camera app
The decision of whether or not to save an image is up to the camera app, not you. There are hundreds of camera apps that might respond to ACTION_IMAGE_CAPTURE, and the developers of those apps can do whatever they want.
There has to be a solution of this issue, be it like once we take a picture we could delete it right away, or there should be an alternate by which we won't allow O.S to save Image,
Take the photo yourself, using the camera APIs or libraries that wrap around them (e.g., CameraKit-Android, Fotoapparat).
There has to be a solution of this issue, be it like once we take
a picture we could delete it right away
Indeed there is. You could specify a path (even using a file provider) where the camera app has to put the image in a file.
Then when the camera app is done you can get the image from that file and then delete the file.
Have a look at Intent.EXTRA_OUTPUT.
Pretty standard your question. You can find a lot of example code on this site.
Final I have found the answer after waiting from past 2 days, yay..It will not save the file as I am just deleting the file after returning from the activity.
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null)
int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToLast();
String imagePath = cursor.getString(column_index_data);
Bitmap bitmapImage = BitmapFactory.decodeFile(imagePath );
Log.d("bitmapImage", bitmapImage.toString()); /*delete file after taking picture*/
Log.d("imagePath", imagePath.toString());
File f = new File(imagePath);
if (f.exists()){
f.delete();
}
sendBroadcast(newIntent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(f)));
Related
What am I doing wrong here? I'm trying to call the intent to get a picture in full size:
takePictureIntent
private void takePictureIntent(int request) {
final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {
File file = null;
try {
file = createImageFile(request);
} catch (Exception e) {
showErrorDialog(getString(R.string.error), getString(R.string.error_saving_picture));
Log.e(TAG, "Error while creating image file.");
}
if (file != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(takePictureIntent, request);
} else {
Log.e(TAG, "Error while creating image file.");
showErrorDialog(getString(R.string.error), getString(R.string.error_saving_picture));
}
}
}
createImageFile
private File createImageFile(final int request) {
final File storageDir = new File(activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES), getString(R.string.app_name));
if (!storageDir.exists()) {
if (!storageDir.mkdirs()) {
Log.e(TAG, "Cannot create parent folders.");
return null;
}
}
File file = null;
try {
file = File.createTempFile("test_", ".jpg", storageDir);
} catch (Exception e) {
Log.e(TAG, "Error while creating temp file.");
}
fileProduct = file;
return file;
}
onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_IMAGE_PRODUCT) {
if (fileProduct == null ||!fileProduct.exists() ||fileProduct.length() == 0) {
showErrorDialog(getString(R.string.error), getString(R.string.error_taking_product_picture));
return;
}
}
Sometimes (yes, sometimes) the length of the resulting file is 0. I know for sure that the folders in private app context exist and the image files as well (with length > 0). Could you please provide some help? I'm on 6.0 on Nexus 5X.
I would start by getting rid of File.createTempFile(). You do not need it, it wastes time, and it might cause some camera apps to want to not store the photo in that file (since the file is already there). Just generate a unique filename yourself. This will incrementally help with your compatibility.
Also, you need to make sure that you are holding onto fileProduct in the saved instance state Bundle, as your app's process may be terminated while the camera app is in the foreground.
However, in general, ACTION_IMAGE_CAPTURE is not very reliable. You are delegating the work to one of hundreds of possible camera apps, and some of those apps have bugs. One such bug is ignoring EXTRA_OUTPUT. So, in onActivityResult(), if you determine that you have a valid fileProduct value, but there is no file there, call data.getData() and see if you have a Uri there. In that case, the camera app may have stored the photo at the location identified by that Uri, and you can use ContentResolver and DocumentFile to try to work with that Uri.
Using this:
final String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
file = new File(storageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
instead of
File.createTempFile()
magically seems to fix the problem. Thanks to CommonsWare for (somehow) pointing me in the right direction.
I tried to take a picture using camera intent and want to get the file path of the full size image. I am following the tutorial from http://developer.android.com/training/camera/photobasics.html. The problem, when I look into the file path in MediaStore.Images.Media.DATA column using MediaStore.Images.Media.EXTERNAL_CONTENT_URI, the image have different path. How do I supply the same file path? I looked at taking a photo and placing it in the Gallery, I though it is simply just change Environment.DIRECTORY_PICTURES to Environment.DIRECTORY_DCIM, but it still didn't work.
Below is my code for taking photo.
private Uri photoPath;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_IMAGE_CAPTURE) {
getContentResolver().notifyChange(photoPath, null);
System.out.println(photoPath);
}
}
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.camera_button) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
try {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String image = "IMG_" + timestamp;
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File photo = File.createTempFile(image, ".jpg", storageDir);
photoPath = Uri.fromFile(photo);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoPath);
startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
}
my code above produce file path /storage/emulated/0/Pictures/IMG_20150805_121624.jpg while it is actually /storage/emulated/0/DCIM/100MEDIA/IMAG0531.jpg in the gallery. the former path is really my image (as I specified it on photoPath), but I want to get the later path instead. How could I do that?
You will have to use Environment.DIRECTORY_DCIM.
The android API DOC clearly has the details of various directories which can be used.
I hope this will help you to save your file to /storage/emulated/0/DCIM/.
I can press a button, open up the native camera app, and successfully take a picture. But then when I check the Gallery or Photos native apps on my phone, the picture isn't saved there. I'm very new to Android so it's likely I'm missing something important in my code.
Questions:
1) Where are these pictures being saved?
2) Can I modify the below code somehow to save instead to internal storage, so all pictures taken with my app are private and only accessible through my app?
3) If I wanted to save these pictures to an object, along with some text/other input, what would be the best way? Should I just save a Uri or some identifier to reference the image later, or save the actual BitMap image?
Any help is greatly appreciated, thanks!
Here is my code to take the picture:
mImageButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageUri = CameraUtils.getOutputMediaFileUri(CameraUtils.MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, REQUEST_IMAGE);
}
}
CameraUtils class taken straight from Google developer guides:
public static Uri getOutputMediaFileUri(int type)
{
return Uri.fromFile(getOutputMediaFile(type));
}
public static File getOutputMediaFile(int type)
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "camera");
if (!mediaStorageDir.exists())
{
if (!mediaStorageDir.mkdirs())
{
return null;
}
}
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 if(type == MEDIA_TYPE_VIDEO)
{
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_" + timeStamp + ".mp4");
}
else
{
return null;
}
return mediaFile;
}
1) By looking at the code, I'd expect the pictures to be saved in a directory called 'camera' which would be found in the Pictures folder on your device (external storage). These might not instantly appear in your gallery, however in later versions of Android (Kitkat and maybe jelly-bean though I can't verify that right now) you should be able to open the Photos app and find them somewhere in there. If that is not the case, then launch a file explorer app (example apps are ASTRO File Manager or X-Plore) and browse to the Pictures/camera directory where you should see your images. The next time your media gets re-indexed (phone reboot, or a re-index triggered from elsewhere), you should see these pictures in your gallery/photo apps. If you want to refresh your media programatically, here might help. Finally, make sure you have the READ_EXTERNAL_STORAGE permission in your Android manifest as specified this (Android doc).
2) If you want to save images to be only available to your application, you need to save them to your application's internal data directory. Take a look at this straight from the Android doc. Make sure to use the MODE_PRIVATE flag.
3) For this, you would want to store the file path somewhere accessible to your app. Either you could save your file paths to a text file with some other text data, or you could use a sqlite database. Finally, you could use an ORM like ORMLite for Android to save a java object which might hold data for your picture and have some fields you want to persist (title, description, path, etc). Here and here is an intro on how to get started with SQLite database in Android (straight from the official doc). If you want to use ORMLite, there is plenty of information on their site here. The developer has spent a lot of time answering StackOverflow questions..
All of your questions can be answered with a few simple Google searches. They are very standard and basic things to do in Android, so you should be able to find a plethora of information and tutorials online.
EDIT:
In response to your comment about the second question. This is what I would probably do (or something similar):
Note that I didn't test this. It's from the top of my head. If you have more issues comment here!
Activity code...
mImageButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageUri = CameraUtils.getOutputMediaFileUri(currentActivity, CameraUtils.MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, REQUEST_IMAGE);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_IMAGE)
{
if (resultCode == RESULT_OK)
{
String pathToInternallyStoredImage = CameraUtils.saveToInternalStorage(this, imageUri);
// Load the bitmap from the path and display it somewhere, or whatever
}
else if (resultCode == RESULT_CANCELED)
{
//Cancel code
}
}
}
CameraUtils class code...
public static Uri getOutputMediaFileUri(int type)
{
return Uri.fromFile(getOutputMediaFile(type));
}
public static File getOutputMediaFile(int type)
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "camera");
createMediaStorageDir(mediaStorageDir);
return createFile(type, mediaStorageDir);
}
private static File getOutputInternalMediaFile(Context context, int type)
{
File mediaStorageDir = new File(context.getFilesDir(), "myInternalPicturesDir");
createMediaStorageDir(mediaStorageDir);
return createFile(type, mediaStorageDir);
}
private static void createMediaStorageDir(File mediaStorageDir) // Used to be 'private void ...'
{
if (!mediaStorageDir.exists())
{
mediaStorageDir.mkdirs(); // Used to be 'mediaStorage.mkdirs();'
}
} // Was flipped the other way
private static File createFile(int type, File mediaStorageDir ) // Used to be 'private File ...'
{
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile = null;
if (type == MEDIA_TYPE_IMAGE)
{
mediaFile = new File(mediaStorageDir .getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
}
else if(type == MEDIA_TYPE_VIDEO)
{
mediaFile = new File(mediaStorageDir .getPath() + File.separator +
"VID_" + timeStamp + ".mp4");
}
return mediaFile;
}
public static String saveToInternalStorage(Context context, Uri tempUri)
{
InputStream in = null;
OutputStream out = null;
File sourceExternalImageFile = new File(tempUri.getPath());
File destinationInternalImageFile = new File(getOutputInternalMediaFile(context).getPath());
try
{
destinationInternalImageFile.createNewFile();
in = new FileInputStream(sourceExternalImageFile);
out = new FileOutputStream(destinationInternalImageFile);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
{
out.write(buf, 0, len);
}
}
catch (IOException e)
{
e.printStackTrace();
//Handle error
}
finally
{
try {
if (in != null) {
in.close();
}
if (out != null) {
in.close();
}
} catch (IOException e) {
// Eh
}
}
return destinationInternalImageFile.getPath();
}
So now you have the path pointing to your internally stored image, which you can then manipulate/load from your onActivityResult.
I'm getting pictures with the next code:
public void foto(View v) {
nom_foto = Environment.getExternalStorageDirectory()+ aptr.ruta_temp + cuadrilla + "/" + medidor + "_"+ cont_foto + ".jpg";
File arch = new File(Environment.getExternalStorageDirectory()+ aptr.ruta_temp+ cuadrilla);
if (!arch.exists())
arch.mkdirs();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
int code = TAKE_PICTURE;
Uri output = Uri.fromFile(new File(nom_foto));
intent.putExtra(MediaStore.EXTRA_OUTPUT, output);
startActivityForResult(intent, code);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PICTURE) {
ImageView iv = (ImageView) findViewById(R.id.minifoto);
if (resultCode == RESULT_OK) {
new MediaScannerConnectionClient() {
private MediaScannerConnection msc = null;
{
msc = new MediaScannerConnection(getApplicationContext(), this);
msc.connect();
}
public void onMediaScannerConnected() {msc.scanFile(nom_foto,null);
}
public void onScanCompleted(String path, Uri uri)
{ msc.disconnect();}};
Toast.makeText(usuario_lectura.this,"Foto N° " + cont_foto + " agregada correctamente", Toast.LENGTH_LONG).show();
cont_foto++;
iv.setVisibility(View.VISIBLE);
iv.setImageBitmap(BitmapFactory.decodeFile(nom_foto));
}
}
if (resultCode == RESULT_CANCELED) {
File file = new File(nom_foto);
if (file.exists())
file.delete();
}
}
}
Everything works properly, the picture has taken correctly and saved on the SD card... But, I have to add a watermarker, including the date... How can I add it?, the camera activity doesn't give me these option...
In order to add a textual or graphical watermark to your image from the camera, you must open the image, edit it in a Canvas with Paint/Graphics overlays, then re-encode it as a .jpg image, and re-save it as a file on the SD card. You can save over the original file from the camera. All of these steps are fairly straightforward.
There is, however, a serious hurdle.
Most devices will not be able to open the full-size image from the camera in a single Bitmap. There is not enough heap memory available. Therefore, you will have to use a scale factor inSampleSize to open your image. Thus, the watermarked image will be forever smaller by some factor than the original from the camera.
I do not think there is any way around this issue :(
Hope someone may give some pointers (or an out right answer)...
Simple app, take an image using the built-in camera app, save the image to a separate application. Be done.
Problem: The camera application saves the image in the default app location (/mnt/sdcard/external_sd/DCIM/Camera) as well as my custom path (in code below).
Both files are exactly the same except for the file name. The external_sd file (the one I want gone) is saved with dashes (-) vs my custom file path saved with underscores. File sizes are exactly the same.
How can I stop this double image issue?
Is there an extra intent option I'm missing?
Or am I doing this completely wrong, missing something?
I'm using a Galaxy S Vibrant.
Code snippet:
private static Uri _outputFileUri;
private static File _file;
private ImageView _image;
private SimpleDateFormat _simpleDateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
_takePicture = (Button) findViewById(R.id.takePicture);
_takePicture.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
_file = new File(Environment.getExternalStorageDirectory() +
"/Android/data/my own folder/files/",
_simpleDateFormat.format(new Date()).toString() +
".jpg");
_outputFileUri = Uri.fromFile(_file);
_intent.putExtra(MediaStore.EXTRA_OUTPUT, _outputFileUri);
startActivityForResult(_intent, CAMERA_ACTIVITY);
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Activity cancelled", Toast.LENGTH_LONG).show();
return;
}
switch (requestCode) {
case CAMERA_ACTIVITY:
if (resultCode == RESULT_OK) {
try{
Bitmap b = MediaStore.Images.Media.getBitmap(getContentResolver(), _outputFileUri);
_image.setImageBitmap(b);
_image.invalidate();
}
catch(Exception e){
e.printStackTrace();
}
}
break;
}
}
This is device-dependent behavior. My observation is that HTC devices do not have this duplication problem, but Samsung devices do.
Please remove the following lines:
_file = new File(Environment.getExternalStorageDirectory() +
"/Android/data/my own folder/files/",
_simpleDateFormat.format(new Date()).toString() +
".jpg");
_outputFileUri = Uri.fromFile(_file);
_intent.putExtra(MediaStore.EXTRA_OUTPUT, _outputFileUri);
Also update the code to get the image from intent:
Bitmap b = (Bitmap) data.getExtras().get("data");
_image.setImageBitmap(b);
_image.invalidate();
This way picture wouldn't be saved on sd card or default location.
I had the same problem and gave up. Sometime later I found out that I was not getting it anymore and I'm not sure what change I made to my code, but I think that it was MediaStore's fault (check my unsolved question: Weird camera Intent behavior)
As you already have the image URI, why don't you use it to set the ImageViews' bitmap?
// void setImageURI(Uri uri)
_image.setImageBitmap(_outputFileUri);
I had this issue and here is how i solved it :
File createImageFile() throws IOException{
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String filename = "IMG_"+timestamp+"_";
File image = File.createTempFile(filename,".jpg",mGalleryFolder );
if (image.length() == 0 ){
boolean delete = image.delete();
}
mLocation = image.getAbsolutePath();
return image;
}
It's not exactly solving but works for me ;)