Stop saving photos using Android native camera
Asked Answered
B

5

13

I am using native Android camera and save file to my application data folder (/mnt/sdcard/Android/data/com.company.app/files/Pictures/). At the same time anther copy of photo is saved to DCIM folder.

This is my code:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String formattedImageName = getDateString() + ".jpg";
File image_file = new File(this.getExternalFilesDir(Environment.DIRECTORY_PICTURES), formattedImageName);
Uri imageUri = Uri.fromFile(image_file);
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
startActivityForResult(intent, REQUEST_FROM_CAMERA);

How can I prevent saving additional copy of image to DCIM folder?

Many Thanks

Biodegradable answered 10/11, 2011 at 11:36 Comment(1)
Hi chinthaka,below code FillPhotoList() will collect all the image in the gallary and than other method movingCapturedImageFromDCIMtoMerchandising() will go through the arralist and finds last image captured and delete it from the DCIM.Sixtyfourmo
S
4

check this code..

private void FillPhotoList() {  
    // initialize the list!    
    GalleryList.clear();    
    String[] projection = { MediaStore.Images.ImageColumns.DISPLAY_NAME }; 
    for(int i=0;i<projection.length;i++)
        Log.i("InfoLog","projection "+projection[0].toString());
    // intialize the Uri and the Cursor, and the current expected size.    
    Cursor c = null;     
    Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 
    Log.i("InfoLog","FillPhoto Uri u "+u.toString());
    // 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.         
            GalleryList.add(c.getString(0)); // adding all the images sotred in the mobile phone(Internal and SD card)

        }            
        while (c.moveToNext());    
    } 
    Log.i(INFOLOG,"gallery size "+ GalleryList.size());
} 

and this is where the method is doing all magic

 /** Method will check all the photo is the gallery and delete last captured and move it to the required folder.
 */
public void movingCapturedImageFromDCIMtoMerchandising()
{

    // 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.  

    for(int i=0;i<projection.length;i++)
        Log.i("InfoLog","on activityresult projection "+projection[i]);
    //+" "+projection[1]+" "+projection[2]+" "+projection[3] this will be needed if u remove the for loop
    Cursor c = null;          
    Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;       
    Log.i("InfoLog","on activityresult Uri u "+u.toString());

    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))        
        {              
            //****u is the place from data will come and projection is the specified data what we want
            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 gallery we built before.     
                boolean bFound = false;               
                for (String sGallery : GalleryList)                  
                {                      
                    if (sGallery.equalsIgnoreCase(c.getString(1)))  
                    {                      
                        bFound = true;
                        Log.i("InfoLog","c.getString(1) "+c.getString(1));
                        break;                    
                    }                   
                }                   
                // To here we looped the full gallery.                   
                if (!bFound)     //the file which is newly created and it has to be deleted from the gallery              
                {                     
                    // 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.      
                            ToastMaker.makeToast(this, "Error Occured", 0);   
                        }                      
                    }                   
                    //****deleting the file which is in the gallery                           
                    Log.i(INFOLOG,"imagePreORNext1 "+imagePreORNext);
                    Handler handler = new Handler();
                    //handler.postDelayed(runnable,300);
                    Log.i(INFOLOG,"imagePreORNext2 "+imagePreORNext);
                    ContentResolver cr = getContentResolver();       
                    cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, BaseColumns._ID + "=" + c.getString(3), null);

                    break;                                          
                }              
            }            
            while (c.moveToNext());   
        }         
    }       

}
Sixtyfourmo answered 10/11, 2011 at 11:52 Comment(10)
Thank you for the reply. Do you thing we can delete mediaStore before sync with Picasa? Do you know any way to stope saving file to mediaStroe?Biodegradable
Can you please let me know what is this "CurrentFile" is ? Where do I have to define this?Biodegradable
it is name of the file which you are giving to the captured imageSixtyfourmo
Amol, is this working? Because when saving duplicated photo it gets it's own file name. We cannot change that.Biodegradable
Thanks Amol. finally I could delete media files.Biodegradable
@krisDroid CurrentFile is the File location where the image is going to be stored.Sixtyfourmo
This is ##### ridiculous. True story.Hord
But what about if user has thousands of pictures on device?Mcgruder
Given that some devices save the image to the DCIM folder and some do not, would deleting the last image on a device that does not save to this folder delete the user's photo's?Fjeld
Any new solution for this problem?Uzbek
T
7

You can use the following : First we get the last saved image by checking which was the last modified image. Then check if last modified time is in the last few seconds. You may also have to check the exact location of where camera stores the image.

private boolean deleteLastFromDCIM() {

        boolean success = false;
        try {
            File[] images = new File(Environment.getExternalStorageDirectory()
                    + File.separator + "DCIM/Camera").listFiles();
            File latestSavedImage = images[0];
            for (int i = 1; i < images.length; ++i) {
                if (images[i].lastModified() > latestSavedImage.lastModified()) {
                    latestSavedImage = images[i];
                }
            }

                    // OR JUST Use  success = latestSavedImage.delete();
            success = new File(Environment.getExternalStorageDirectory()
                    + File.separator + "DCIM/Camera/"
                    + latestSavedImage.getAbsoluteFile()).delete();
            return success;
        } catch (Exception e) {
            e.printStackTrace();
            return success;
        }

    }
Tardigrade answered 2/3, 2012 at 11:37 Comment(2)
Im thinking what if your app happens to be on a phone which doesn't save photos to that directory "DCIM/Camera/" wouldn't you run a risk of deleting some poor user's family album?Alevin
a solution to @ Sixtoo coment is to chek time - if file has last modification couple seconds ago - only then delete itHouck
G
6

Unfortunately, some smart phones save images in another folder such as DCIM/100MEDIA. So can't rely to these solution. I prefer use this way:

String[] projection = new String[] {
     MediaStore.Images.ImageColumns._ID,
     MediaStore.Images.ImageColumns.DATA,
     MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
     MediaStore.Images.ImageColumns.DATE_TAKEN,
     MediaStore.Images.ImageColumns.MIME_TYPE};     

final Cursor cursor = managedQuery(
     MediaStore.Images.Media.EXTERNAL_CONTENT_URI,projection, null, null,
     MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC"); 

if(cursor != null){
     cursor.moveToFirst();
     // you will find the last taken picture here and can delete that
}

I tried to find out if a second copy exists and delete the copy. I used the above code to find the last taken picture.

Notice: Don't use cursor.close(); after using managedQuery, Leave the cursor for the Android system to manage and don't call that. You can see managedQuery()

Notice2: The managedQuery method is deprecated and it should be avoided, implement CursorLoaders instead.

Gravettian answered 8/4, 2013 at 6:53 Comment(3)
CAREFUL:this is very very dangerous.. in some devices, the pictures we take from our app are not copying to gallery. In that case, if we delete the last taken picture, its returning the picture taken from the camera app, so we end up deleting the wrong picture, not the picture taken from our app. So, the bottom line is, delete the last taken picture from gallery only for the devices which creates the 2nd copy(e.g HTC One M8).Mikiso
@Mikiso : How do we know that 2nd copy is created? I am facing this issue on Moto G4 Plus.Weidman
no way, if you use camera intent.. if you don't want to create 2nd copy, you have to implement Camera API in your application.Mikiso
S
4

check this code..

private void FillPhotoList() {  
    // initialize the list!    
    GalleryList.clear();    
    String[] projection = { MediaStore.Images.ImageColumns.DISPLAY_NAME }; 
    for(int i=0;i<projection.length;i++)
        Log.i("InfoLog","projection "+projection[0].toString());
    // intialize the Uri and the Cursor, and the current expected size.    
    Cursor c = null;     
    Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 
    Log.i("InfoLog","FillPhoto Uri u "+u.toString());
    // 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.         
            GalleryList.add(c.getString(0)); // adding all the images sotred in the mobile phone(Internal and SD card)

        }            
        while (c.moveToNext());    
    } 
    Log.i(INFOLOG,"gallery size "+ GalleryList.size());
} 

and this is where the method is doing all magic

 /** Method will check all the photo is the gallery and delete last captured and move it to the required folder.
 */
public void movingCapturedImageFromDCIMtoMerchandising()
{

    // 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.  

    for(int i=0;i<projection.length;i++)
        Log.i("InfoLog","on activityresult projection "+projection[i]);
    //+" "+projection[1]+" "+projection[2]+" "+projection[3] this will be needed if u remove the for loop
    Cursor c = null;          
    Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;       
    Log.i("InfoLog","on activityresult Uri u "+u.toString());

    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))        
        {              
            //****u is the place from data will come and projection is the specified data what we want
            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 gallery we built before.     
                boolean bFound = false;               
                for (String sGallery : GalleryList)                  
                {                      
                    if (sGallery.equalsIgnoreCase(c.getString(1)))  
                    {                      
                        bFound = true;
                        Log.i("InfoLog","c.getString(1) "+c.getString(1));
                        break;                    
                    }                   
                }                   
                // To here we looped the full gallery.                   
                if (!bFound)     //the file which is newly created and it has to be deleted from the gallery              
                {                     
                    // 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.      
                            ToastMaker.makeToast(this, "Error Occured", 0);   
                        }                      
                    }                   
                    //****deleting the file which is in the gallery                           
                    Log.i(INFOLOG,"imagePreORNext1 "+imagePreORNext);
                    Handler handler = new Handler();
                    //handler.postDelayed(runnable,300);
                    Log.i(INFOLOG,"imagePreORNext2 "+imagePreORNext);
                    ContentResolver cr = getContentResolver();       
                    cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, BaseColumns._ID + "=" + c.getString(3), null);

                    break;                                          
                }              
            }            
            while (c.moveToNext());   
        }         
    }       

}
Sixtyfourmo answered 10/11, 2011 at 11:52 Comment(10)
Thank you for the reply. Do you thing we can delete mediaStore before sync with Picasa? Do you know any way to stope saving file to mediaStroe?Biodegradable
Can you please let me know what is this "CurrentFile" is ? Where do I have to define this?Biodegradable
it is name of the file which you are giving to the captured imageSixtyfourmo
Amol, is this working? Because when saving duplicated photo it gets it's own file name. We cannot change that.Biodegradable
Thanks Amol. finally I could delete media files.Biodegradable
@krisDroid CurrentFile is the File location where the image is going to be stored.Sixtyfourmo
This is ##### ridiculous. True story.Hord
But what about if user has thousands of pictures on device?Mcgruder
Given that some devices save the image to the DCIM folder and some do not, would deleting the last image on a device that does not save to this folder delete the user's photo's?Fjeld
Any new solution for this problem?Uzbek
C
3

A nice solution by Parth. But it's good for Samsungs that keep images in DCIM/Camera. Some phones - Sony Ericssons, HTCs keep them in folders like DCIM/100MEDIA, DCIM/100ANDRO so I have slightly modified the code:

 private boolean deleteLastFromDCIM() {
    boolean success = false;
    try {           
        //Samsungs:
        File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "DCIM/Camera");
        if(!folder.exists()){ //other phones:
            File[] subfolders = new File(Environment.getExternalStorageDirectory() + File.separator + "DCIM").listFiles();
            for(File subfolder : subfolders){
                if(subfolder.getAbsolutePath().contains("100")){  
                    folder = subfolder;
                    break;
                }
            }
            if(!folder.exists())
                return false;
        }

        File[] images = folder.listFiles();
        File latestSavedImage = images[0];
        for (int i = 1; i < images.length; ++i) {
            if (images[i].lastModified() > latestSavedImage.lastModified()) {
                latestSavedImage = images[i];
            }
        }            
        success = latestSavedImage.delete();
        return success;
    } catch (Exception e) {
        e.printStackTrace();
        return success;
    }

}
Carlie answered 26/3, 2013 at 14:9 Comment(3)
This isn't doing anything for me. My app doesn't crash, but the photo persists. Could you shine some light its usage?Aphasia
This does remove the image for me, but in the gallery App I still get a broken thumbnail where the image was.Fjeld
You know guys, that was a solution that worked in a particular situation in a particular app on particular phones. In the ever changing (wild should I say?) Android world nothing is constant not persistent. Also, not every poster has time to keep his answers up to date for every device...Carlie
S
0

I am encountering a similar problem with the Moto Z Force (7.1.1). I have the MediaStore.EXTRA_OUTPUT defined on the intent, but a duplicate file is still created in the camera directory.

I need to test on other devices, but here's an approach I took regarding this issue. Rather than trying to find the specific camera directory, I'm using the MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME location.

Here's my code snippet:

private void removeCameraDuplicate() {
    String[] proj = {
        MediaStore.Images.ImageColumns.DATA,
        MediaStore.Images.ImageColumns._ID };

    String selection = MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME + " = ? ";
    String[] selectionArgs = new String[] { "Camera" };

    Cursor cursor = mActivity.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj, selection, selectionArgs, MediaStore.Images.ImageColumns.DATE_TAKEN + " desc");

    if (cursor != null) {
        int idxPath = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);

        if (cursor.getCount() > 0 && idxPath > -1 && cursor.moveToFirst()) {
            File original = new File(mMediaPath);
            File cameraDupe = new File(cursor.getString(idxPath));
            if (original.exists() && cameraDupe.exists()) {
                LogUtils.LOGE("***> camera", "original " + original.length());
                LogUtils.LOGE("***> camera", "original " + original.lastModified());

                LogUtils.LOGE("***> camera", "duplicate " + cameraDupe.length());
                LogUtils.LOGE("***> camera", "duplicate " + cameraDupe.lastModified());

                if (original.length() == cameraDupe.length() && original.lastModified() == cameraDupe.lastModified()) {
                    if (cameraDupe.delete()) {
                        LogUtils.LOGE("***> camera", "duplicate deleted");
                    }
                }
            }
        }
        cursor.close();
    }
}
Stripteaser answered 8/8, 2018 at 16:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.