Deleting a gallery image after camera intent photo taken
Asked Answered
R

13

67

I know this has been asked in many different ways but I still can not seem to delete the gallery image from the default folder. I'm saving the file to the SD card correctly and I can delete that file fine, but the default gallery image file that shows under the folder Camera will not delete.

I would like the image to delete once the activity is returned since the file is already stored on the SD card under /Coupon2.

Any suggestions?

public void startCamera() {
    Log.d("ANDRO_CAMERA", "Starting camera on the phone...");

    mManufacturerText = (EditText) findViewById(R.id.manufacturer);
    String ManufacturerText = mManufacturerText.getText().toString();
    String currentDateTimeString = new Date().toString();

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    File filedir = new File(Environment.getExternalStorageDirectory()+"/Coupon2");
    filedir.mkdirs();

    File file = new File(Environment.getExternalStorageDirectory()+"/Coupon2", ManufacturerText+"-test.png");
    outputFileUri = Uri.fromFile(file);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);

    startActivityForResult(intent, CAMERA_PIC_REQUEST);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CAMERA_PIC_REQUEST && resultCode == -1) {  
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.putExtra("crop", "true");
        intent.putExtra("scale", "true");

        intent.putExtra("return-data", false);
        intent.setDataAndType(outputFileUri, "image/*");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        startActivityForResult(intent, CAMERA_CROP_REQUEST);
    }else { 
        SetImage();
        saveState();
    }
}
Remorseful answered 17/6, 2011 at 18:30 Comment(4)
I guess there is no real good way to do this since I am using MediaStore.ACTION_IMAGE_CAPTURE and not a custom camera activity. If there is anyone who has a way of saving the output file to the EXTRA_OUTPUT folder without saving it to the gallery, please let me know.Remorseful
We have also found this behavior as well but only on some phones. (Notably the myTouch 3G.) Other phones save only to the EXTRA_OUTPUT file as intended.Miliary
#4515532 appears to be the same issue, and suggests it also happens on LG Ally phones.Miliary
Any more concrete devices which show this behaviour? As of today? Or a emulator configuration? Need to test this...Sofer
S
71

My application requires me to call an intent to take a photo. The photo cannot be in the gallery but instead must be in a specific directory on the SD card.

Originally I just used the EXTRA_OUTPUT, but I soon discovered the following: - Some devices use it completely and skip the gallery. - Some devices ignore it completely and ONLY use the gallery. - Some devices really suck and save a full sized image to the gallery, and save a thumbnail only to the location I wanted. (HTC you know who you are...)

So, I can't blindly delete a gallery file when I'm done. The last added photo may or may not be the one I want to remove. Also, I may have to copy that file replacing my own afterwards. Because my activity is 2000 lines, and my company wouldn't want all of our code being posted, I'm posting only the methods involved in doing this. Hopefully this helps.

Also, I'll state, this is my first Android application. I wouldn't be surprised if there was a better way to do this that I just don't know about, but this is what's working for me!

So, here is my solution:

First, in my application context I define a variable as follows:

public ArrayList<String> GalleryList = new ArrayList<String>();

Next, in my activity, I define a method to get a list of all photos in the gallery:

private void FillPhotoList()
{
   // initialize the list!
   app.GalleryList.clear();
   String[] projection = { MediaStore.Images.ImageColumns.DISPLAY_NAME };
   // intialize the Uri and the Cursor, and the current expected size.
   Cursor c = null; 
   Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
   //
   // Query the Uri to get the data path.  Only if the Uri is valid.
   if (u != null)
   {
      c = managedQuery(u, projection, null, null, null);
   }

   // If we found the cursor and found a record in it (we also have the id).
   if ((c != null) && (c.moveToFirst())) 
   {
      do 
      {
        // Loop each and add to the list.
        app.GalleryList.add(c.getString(0));
      }     
      while (c.moveToNext());
   }
}

Here's a method to return a unique file name for my new image:

private String getTempFileString()
{
   // Only one time will we grab this location.
   final File path = new File(Environment.getExternalStorageDirectory(), 
         getString(getApplicationInfo().labelRes));
   //
   // If this does not exist, we can create it here.
   if (!path.exists())
   {
      path.mkdir();
   }
   //
   return new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg").getPath();
}

I have three variables in my Activity that store information for me about a current file. A string (path), a File variable, and a URI to that file:

public static String sFilePath = ""; 
public static File CurrentFile = null;
public static Uri CurrentUri = null;

I never set these directly, I only call a setter on the file path:

public void setsFilePath(String value)
{
   // We just updated this value. Set the property first.
   sFilePath = value;
   //
   // initialize these two
   CurrentFile = null;
   CurrentUri = null;
   //
   // If we have something real, setup the file and the Uri.
   if (!sFilePath.equalsIgnoreCase(""))
   {
      CurrentFile = new File(sFilePath);
      CurrentUri = Uri.fromFile(CurrentFile);
   }
}

Now I call an intent to take a photo.

public void startCamera()
{
   Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
   // Specify the output. This will be unique.
   setsFilePath(getTempFileString());
   //
   intent.putExtra(MediaStore.EXTRA_OUTPUT, CurrentUri);
   //
   // Keep a list for afterwards
   FillPhotoList();
   //
   // finally start the intent and wait for a result.
   startActivityForResult(intent, IMAGE_CAPTURE);
}

Once this is done, and the activity comes back, here is my code:

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
   if (requestCode == IMAGE_CAPTURE)
   {
      // based on the result we either set the preview or show a quick toast splash.
      if (resultCode == RESULT_OK)
      {
         // This is ##### ridiculous.  Some versions of Android save
         // to the MediaStore as well.  Not sure why!  We don't know what
         // name Android will give either, so we get to search for this
         // manually and remove it.  
         String[] projection = { MediaStore.Images.ImageColumns.SIZE,
                                 MediaStore.Images.ImageColumns.DISPLAY_NAME,
                                 MediaStore.Images.ImageColumns.DATA,
                                 BaseColumns._ID,};
         //    
         // intialize the Uri and the Cursor, and the current expected size.
         Cursor c = null; 
         Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
         //
         if (CurrentFile != null)
         {               
            // Query the Uri to get the data path.  Only if the Uri is valid,
            // and we had a valid size to be searching for.
            if ((u != null) && (CurrentFile.length() > 0))
            {
               c = managedQuery(u, projection, null, null, null);
            }
            //   
            // If we found the cursor and found a record in it (we also have the size).
            if ((c != null) && (c.moveToFirst())) 
            {
               do 
               {
                  // Check each area in the gallary we built before.
                  boolean bFound = false;
                  for (String sGallery : app.GalleryList)
                  {
                     if (sGallery.equalsIgnoreCase(c.getString(1)))
                     {
                        bFound = true;
                        break;
                     }
                  }
                  //       
                  // To here we looped the full gallery.
                  if (!bFound)
                  {
                     // This is the NEW image.  If the size is bigger, copy it.
                     // Then delete it!
                     File f = new File(c.getString(2));

                     // Ensure it's there, check size, and delete!
                     if ((f.exists()) && (CurrentFile.length() < c.getLong(0)) && (CurrentFile.delete()))
                     {
                        // Finally we can stop the copy.
                        try
                        {
                           CurrentFile.createNewFile();
                           FileChannel source = null;
                           FileChannel destination = null;
                           try 
                           {
                              source = new FileInputStream(f).getChannel();
                              destination = new FileOutputStream(CurrentFile).getChannel();
                              destination.transferFrom(source, 0, source.size());
                           }
                           finally 
                           {
                              if (source != null) 
                              {
                                 source.close();
                              }
                              if (destination != null) 
                              {
                                 destination.close();
                              }
                           }
                        }
                        catch (IOException e)
                        {
                           // Could not copy the file over.
                           app.CallToast(PhotosActivity.this, getString(R.string.ErrorOccured), 0);
                        }
                     }
                     //       
                     ContentResolver cr = getContentResolver();
                     cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                        BaseColumns._ID + "=" + c.getString(3), null);
                     break;                        
                  }
               } 
               while (c.moveToNext());
            }
         }
      }
   }      
}
Spontaneous answered 6/7, 2011 at 16:56 Comment(14)
Thanks this helped resolve the problem on those stupid thumbnail-returning devices. This is also the same problem millions of other stackoverflow posts are crying about "camera photo orientation on 2.1 devices".Boondocks
Instead of keeping an ArrayList of gallery items, consider using a HashMap. Presently your code nests looping through the images in the Gallery twice, so with N images you're running n^2 comparisons. This will cause noticeable lag on devices with many images. If you use a HashMap, you'd use the lowercase file name as the key. Then you can check the existence of a file using containsKey, turning this into an O(n) operation.Felicitasfelicitate
Hi! I followed your code and I'm facing a wired behavior. I get the picture and save it into my database. In another point of the program, I display all the pictures that I have in my DB. However, the orientation is wrong. I checked also the database and it's saved also with a wrong orientation. Is it happening to you too?Surprise
Finuka - No, orientation is not incorrect for me. Since this original post, I've added some additional code to resize large images to always be under 3MB in file size, and I've implemented abscondment's suggestion of using the hashmap. I never had an orientation issue after any of the changes, nor originally.Spontaneous
@MarcoS To create a hashmap, do: HashMap<String, Integer> picMap = new HashMap<String, Integer>(); for (int i = 0; i < app.GalleryList.size(); i++) { picMap.put(app.GalleryList.get(i), i); } Then to check for file existance, check: boolean bFound = picMap.containsKey(c.getString(1));Spontaneous
@Spontaneous Why not use HashSet<String> instead? It's not like you're using the integer that you store with the StringDogcatcher
@Dogcatcher You're absolutely correct. I am used to adding a field to function like a PK does - something to reference uniquely. It's not always needed, just something I've done. In this case the string is guaranteed to be unique already and this was unnecessary.Spontaneous
It's working for Images but It's not working for video files. I used by changing MediaStore.Images.ImageColumns to MediaStore.Video.VideoColumns... How to do for Video files...Bernice
Don't you people think on those device who doesn't show this behavior it will delete other files or last taken file from sdcard check it firstBrachiate
No, since it would only find photos taken after the intent was called. It doesn't just blindly delete a file.Spontaneous
How about avoiding the putExtra() minefield altogether? Just let the camera app save the image wherever it wants. Then find it in onActivityResult, get its path, copy it to your own location, then delete the original (both the gallery item and the file). It should be a cleaner approach (still ridiculously awkward, of course). Would that work?Adaminah
I've found another issue that will make your code fail for LG G2. My device saves every image it takes into a specific folder. If you call the intent to take a picture, take one, click to 'cancel', take another and then click 'go', it'll save both images. So it may occur that you copy the discarted image into your destination File.Silicle
Careful with this code - we used it in a production app and found that several users had their entire galleries deleted the first time that this code ran. It looks like their gallery list wasn't properly populated after calling FillPhotoList the first time, and was then populated during the process of taking a photo. Obviously a huge privacy concern. Any ideas?Precisian
There's a break after a single delete so I'm not sure why you could get more than one deleted. This code has evolved over time since it was posted but at the time I posted it I had around 1000 users that it ran on. I notice above I still used Hungarian notation at the time too... Took me a while to break that habit!Spontaneous
R
19

This will delete the file from gallery:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == CAMERA_PIC_REQUEST && resultCode == RESULT_OK) { 

        /* Copy the file to other directory or whatever you want */

        // mContext is the context of the activity
        mContext.getContentResolver().delete(data.getData(), null, null);
    }
 }

About the EXTRA_OUTPUT not standard behaviour. I think this pseudo-algorithm should work in every case:

1) Do not use EXTRA_OUTPUT. The image/photo always will go to the gallery location.

2) Copy the file from the gallery location to the desired location.

3) Remove (with the upper code) the file from gallery.

But of course it seems to be too perfect... in some devices (for example the original Galaxy Tab with android 2.3), you have to use EXTRA_OUTPUT with ACTION_IMAGE_CAPTURE, without this the intent does not work.

Retouch answered 30/1, 2013 at 12:39 Comment(1)
There's nothing in the documentation which states that intent.getData() will be the URI of the image. There is anecdotal evidence based on SO comments to suggest that it is not set on some phones.Rictus
G
16

If someone is looking for a simpler work around to this problem, here is how I solved the issue.

I have a capture button and when it is pressed the intent is sent, what I added is that I also go and get the last id from image mediastore and store it:

/**
 * Gets the last image id from the media store
 * @return
 */
private int getLastImageId(){
    final String[] imageColumns = { MediaStore.Images.Media._ID };
    final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
    final String imageWhere = null;
    final String[] imageArguments = null;
    Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, imageWhere, imageArguments, imageOrderBy);
    if(imageCursor.moveToFirst()){
        int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
        imageCursor.close();
        return id;
    }else{
        return 0;
    }
}

Then when the activity returns I run this code to checks for the last image id before capture, then queries for images after capture have an id larger then recorded and if it is more then one deletes the record located at the location I specified for the camera to save in.

/*
 * Checking for duplicate images
 * This is necessary because some camera implementation not only save where you want them to save but also in their default location.
 */
final String[] imageColumns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_TAKEN, MediaStore.Images.Media.SIZE, MediaStore.Images.Media._ID };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
final String imageWhere = MediaStore.Images.Media._ID+">?";
final String[] imageArguments = { Integer.toString(MyActivity.this.captureLastId) };
Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, imageWhere, imageArguments, imageOrderBy);
if(imageCursor.getCount()>1){
    while(imageCursor.moveToNext()){
        int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
        String path = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
        Long takenTimeStamp = imageCursor.getLong(imageCursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN));
        Long size = imageCursor.getLong(imageCursor.getColumnIndex(MediaStore.Images.Media.SIZE));
        if(path.contentEquals(MyActivity.this.capturePath)){
            // Remove it
            ContentResolver cr = getContentResolver();
            cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
            break;
        }
    }               
}
imageCursor.close();

For me this was a much simpler solution, and I tested on my HTC which was having this issue.

Another side note, I originally used *DATE_TAKEN* not *_ID* as the parameter but there seems to be some bug that on the emulator some of the images being captured through the intent had their millsecond *DATE_TAKEN* times multiplied by a 1000 so I switched to *_ID* which seems to be much more robust.

Gurnard answered 19/12, 2011 at 0:15 Comment(9)
@Emil MyActivity.this.captureLastId is the call for getLastImageId()? If it's that, your code doesn't work for me. The imageCursor is empty for me... the code inside the if(imageCursor.getCount()>1) is not executed. And the managedQuery method is deprecated.Maddalena
@Maddalena Treat this a pseudocode to get this gist of the method which you can implement, don't just copy the code and expect it work.Gurnard
@Emil your answer is not pseudocode. If I see normal code, I expect it to work. If you know that your answer is not complete or that is necessary more code, advise it somewhere, and tell the reader what he needs to do to make it work. That would make your answer more complete and succesful.Maddalena
@Maddalena I simply described a simple method for solving this issue, the code is there to guide you. I'm not going to spend time warning people that code may not work or that some methods will eventually become deprecated, because I don't expect any competent programmer to just copy snippets of code and complain about it not working.Gurnard
@Emil don't worry, I solved my problem in another way. But you have to think that here, in StackOverflow, there are competent programmers, but also beginners. And that's the reason why you don't have more votes in this answer. This type of question is asked by beginners, is a common problem with the native camera app, and your answer is just for "competent programmers".Maddalena
@Maddalena I don't care for your attitude. This has nothing to do with being a beginner, if you want to just copy and paste code - don't confuse what your are doing with programming.Gurnard
@Emil I asked 3 months ago, you didn't answer and I managed to solve my doubt on my own. That's OK. But three months later, you get angry with my question. It's not hard to understand that complete answers are better than partial answers. If you don't want to complete your answer, just don't do it, but don't blame me for asking. You have a haughty attitude.Maddalena
Thanks, this works for me. A comment - do not use cursor.close() when you obtain it from managedQuery (there is a warning there in the doc not to use it), unless you call stopManagingCursor(cursor), which I would advise anyway. Also, why imageCursor.getCount() > 1 and not imageCursor.getCount() > 0? Typo?Count
@Count I have not tried using the code but from what Emil wrote, it seems that he is querying for all photos after a certain time period and expects to get at least 1 photo. If you get more than 1 photo, then we assume that the photo was saved in multiple locations so we should delete one of them. I could reading it wrong though.Janeljanela
T
5

Well the whole problem I think is coming from the fact that you are expecting a certain result from another application which is not happening. Which is (just to be clear) -

  • Launch an activity that can take picture, since your application doesn't capture images.
  • Tell the other application where you want to save the picutre
  • Use the saved image at the location you specified.
  • But the problem is the other application has also saved the image at a different location also, which you don't want it to.

Now lets look at it from the other application perspective, which is capturing the image. Lets consider two scenarios (Which is possible) -

  • First, The application is launched with the option of the fileName or location where the image is to be saved.
  • Second, the application is launched without any extra information like the fileName or location where the image is to be saved.(This could happen if the capturing app is lauched directly from the menu)

Now ideally what should have happenend is if there is extra information like fileName or location then he should have used that location if not then he can use his own. But alas we are from an ideal world and since nothing is written in stone on what should happen when you launch a camera application the camera app developer will have his own interpretation.

Since different devices have different camera application set as the default(yes, the stock camera is usually replaced) the results obtained are/will be different.

So in some camera's it might be saved in only one place in other it might be saved in the Camera folder as well (since the camera application might always save the captured image in the camera folder and saving it in a different location is bonus given by the application)

If you just pass a fileName to the camera application should the application return after just taking one photo? I think not. So what should in such a scenario? It's all very ambiguous or an gray area.

Now if you don't want it to be saved in the Camera folder then find out if can just get the filename of the recently captured image and then delete it from your application. Or don't tell the camera application where it needs to be saved, just get the filename and move it location that you want.

If you don't get the filename then you are at the mercy of the other application developer. (Hey! it's not his fault either, he just designed it the way he wants!)

Trieste answered 27/6, 2011 at 10:3 Comment(0)
F
2

I think you can't do what you want. That's sad but I can't find another answer.

If you work with google Camera implementation it works fine. It just doesn't store photo to gallery in EXTRA_OUTPUT is specified.

But when you face some other devices they may do something completely different. That's because HTC, LG and maybe some others have custom Camera implementation and you can't do anything about that. You can leave it as it is or write your own Camera that will work exactly the way you need it.

Actually it's not related to this question, but one day you'll find out that CROP intent doesn't work on some devices (http://groups.google.com/group/android-developers/browse_frm/thread/2dd647523926192c/4b6d087073a39607?tvc=1&pli=1). So again if you need it you'll have to write it yourself.

Fourthclass answered 27/6, 2011 at 14:54 Comment(0)
D
2

This is not an easy task to solve but can approach a tricky method.If any one need a simple and working solution for this. Try the below code:

  1. Save the current time in milli second before calling the camera intent.
  2. OnActivityResult query the image uri whose taken date is greater than the millisecond in step1. And delete the file. Thats it.
String[] projection = {MediaStore.Images.ImageColumns.SIZE,
                MediaStore.Images.ImageColumns.DISPLAY_NAME,
                MediaStore.Images.ImageColumns.DATA,
                BaseColumns._ID,MediaStore.Images.ImageColumns.DATE_ADDED};
        final String imageOrderBy = MediaStore.Images.Media._ID + " DESC";
        final String selection = MediaStore.Images.Media.DATE_TAKEN+" > "+mImageTakenTime;
        //// intialize the Uri and the Cursor, and the current expected size.
        Cursor c = null;
        Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        c = getActivity().managedQuery(u, projection, selection, null, imageOrderBy);
        if(null != c && c.moveToFirst()){
            ContentResolver cr = getActivity().getContentResolver();
            cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    BaseColumns._ID + "=" + c.getString(3), null);
        }
Derosa answered 22/1, 2015 at 11:53 Comment(0)
C
1

Look here - that's a piece of code which saves picture to EXTRA_OUTPUT folder without saving it to gallery. In this way in my application I used to grab picture directly from camera and then delete taken picture.

Columbian answered 23/6, 2011 at 5:2 Comment(1)
Your code is functionally identical to the code of the asker and to the code in my project. It works on some phones. It does not work on others, which write to EXTRA_OUTPUT and some other place.Miliary
M
1

This is the code I use which takes a pic and saves it at the location specified

Uri outputFileUri;

public void takePhoto() {
    File directory = new File(Environment.getExternalStorageDirectory()
            + "/HI-Tech" + "/");

    if (!directory.exists()) {
        directory.mkdir();
    }

    int count = 0;
    if (directory != null) {
        File[] files = directory.listFiles();
        if (files != null) {
            count = files.length;
        }
    }
    count++;
    String imagePath = "IMAGE_" + count + ".jpg";
    File file = new File(directory, imagePath);
    outputFileUri = Uri.fromFile(file);

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(intent, JobActivity.TAKE_PIC);
}

I then handle the response.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    try {
        if (resultCode == RESULT_OK) {
            if (requestCode == JobActivity.TAKE_PIC) {
                Bitmap bitmap = decodeFile(new File(outputFileUri.getPath()), 160, 120);
    } catch (Exception e) {
        Log.e("Error", "Unable to set thumbnail", e);
    }
}

I had to declare the outputFileUri as a global variable as I found no way of acquiring the saved path onActivityResult. By passing the outputFileUri you will notice that the image isn't saved in the Camera folde but at the location specified. I've tried this code on my Nexus1 and a cheap samsung thing.

Hope this helps

Mastership answered 23/6, 2011 at 23:44 Comment(1)
Your code is functionally identical to the code of the asker and to the code in my project. It works on some phones. It does not work on others, which write to EXTRA_OUTPUT and some other place.Miliary
B
1

I also was struggling with this issue. By the way, this issue is marked as Obsolete in the Android bug tracker. For some reason Android team doesn't consider this as a bug anymore. Maybe because this is manufacturer-related.

It seems that all solutions (from this thread and other blog posts etc.) form the following algorithm:

  1. Save a unique identifier of the last taken photo;
  2. Launch camera activity using Intent with EXTRA_OUTPUT ;
  3. Take a photo and check whether an id of the last taken photo in Gallery has changed to decide whether it should be deleted.

Something similar is proposed in the accepted answer.

But I found that such approach cannot be used in a production code. For example, let's image a simple situation:

You store some id of the last taken photo in Gallery and launch camera activity. When the user takes a photo on some devices the camera activity shows a dialog with Cancel and OK buttons (or something like that). And the logic behind them is as follows:

  • if the user presses Cancel he returns to the camera activity and can continue to take photos.
  • if he/she (the user) presses OK button the camera activity returns the result to your app.

The important notes here: it turns out that on some devices (I tested on LG and HTC) the image can be already saved while this dialog being presented.

Now imagine what if the user for some reason decides to tap Home button and starts another app (e.g. another camera app where the user can take different photos!). And then returns to your app where that dialog is still presented and presses OK. Obviously in that case your app your will delete the wrong file... and disappoint the user :(

So after a lot of researching I decided that the best approach to overcome this problem is to write your own camera engine or just use some third-party libs like this: material camera.

Brinkema answered 8/11, 2016 at 19:24 Comment(1)
I think using own or lib camera implementation is best choice, especially since 4.4?, when it become not possible to delete/move files created by other applications.Wolk
L
0

Your best bet is probably to handle the Camera class directly, and then store the jpeg or raw returned in the callback where you want.

Alternatively, you could try and delete the taken image by _id from the content provider for media after it's been added. Just find it by query and delete it via the ContentResolver.delete, not sure about the implementation though.

Ludicrous answered 27/6, 2011 at 21:54 Comment(0)
S
0

After struggeling with this for some time, I bit the bullet and wrote my own camera caputere activity. I am convinced this is much more portable and safer than the MediaStore.ACTION_IMAGE_CAPTURE solutions. The image will be stored where you store it and nowhere else and you are not in danger to delete some unrelated file by accident. Also, it is possible to adapt the actual camera function exactly to the requirements.

For portability reasons, I used the Camera class, not camera2.

It is worth to note that the camera parameters should all be set, especially picture size, focus mode and flash mode, they all may be in an unexpected state when starting the camera.

Posting this as an answer, not as a comment, because in my opinion it is the correct answer resulting in minimal effort.

Sofer answered 15/3, 2017 at 11:42 Comment(0)
B
0
protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {

    Bitmap photo = (Bitmap) data.getExtras().get("data");
    Uri tempUri = Utils.getUri(getActivity(), photo);
    File finalFile = new File(getRealPathFromURI(tempUri));
    finalFile.delete();
    }  
}


public String getRealPathFromURI (Uri contentUri) {
    String path = null;
    String[] proj = { MediaStore.MediaColumns.DATA };
    Cursor cursor = getActivity().getContentResolver().query(contentUri, proj, null, null, null);
    if (cursor.moveToFirst()) {
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
        path = cursor.getString(column_index);
    }
    cursor.close();
    return path;
}
Brumby answered 16/4, 2018 at 12:23 Comment(0)
A
0

Below code not only deletes the image file but also deletes the 0Byte file that gets left behind when filw is deleted. I observed this 0Byte ghost file behavior in Android 10.

    val fileToDelete = File(photoUri.path)
    if (fileToDelete.exists()) {
        if (fileToDelete.delete()) {
            if (fileToDelete.exists()) {
                fileToDelete.canonicalFile.delete()
                if (fileToDelete.exists()) {
                    getApplicationContext().deleteFile(fileToDelete.name)
                }
            }
            Log.e("File", "Deleted " + savedPhotoUri?.path)
        } else {
            Log.e("File", "not Deleted " + savedPhotoUri?.path)
        }
    }
Abase answered 17/4, 2020 at 11:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.