8

In my app you it takes a picture saves it to the SD card then user gets to chose what to do with it. Delete, save, or send. If you press delete. I call File.delete() it deletes the files when I go look in the gallery and then when I sometimes go back later I see a black image saying file cannot load. That image is the one I attempted to delete earlier. What is wrong with this and why doesn't it completely go away?

How I save the image:

public static File getOutputMediaFile(byte[] data){
    image= BitmapFactory.decodeByteArray(data, 0, data.length);
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FrontFlash");
    // 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());
    File mediaFile;
    mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
    return mediaFile;
}
@Override
public void onPictureTaken(byte[] data, Camera camera){
    pictureFile = Util.getOutputMediaFile(data);
    if (pictureFile == null){
        Toast.makeText(this, "Couldn't create file", Toast.LENGTH_SHORT).show();
    }
    else{
        try{
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        }
        catch (FileNotFoundException e){
            Toast.makeText(this, "File not found exception", Toast.LENGTH_SHORT).show();
        }
        catch (IOException e){
            Toast.makeText(this, "IO Exception", Toast.LENGTH_SHORT).show();
        }
    }

    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FrontCam"))));
    String photopath = pictureFile.getPath().toString();

//Rotates the image

bmp = BitmapFactory.decodeFile(photopath);
matrix = new Matrix();
matrix.postRotate(270);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
    FileOutputStream fOut;
    try {
        fOut = new FileOutputStream(pictureFile);
        bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
        fOut.flush();
        fOut.close();
    } catch (FileNotFoundException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

where onClick where image is delete

public void exit( View view){
    deleted = pictureFile.delete();
    //startActivity(home);
    close();
    finish();
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Will Jamieson
  • 918
  • 1
  • 16
  • 32
  • 1
    That's because the gallery hasn't been updated. Trigger a media scan and it should be fine. – Karthik Balakrishnan Jun 19 '13 at 02:54
  • is that not what this does when it saves the photo? `sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FrontCam"))));` – Will Jamieson Jun 19 '13 at 02:57
  • if not please show me what to put after I delete the image – Will Jamieson Jun 19 '13 at 02:57
  • Just check the file in your sdcard not the image in the gallery. – tianwei Jun 19 '13 at 03:09
  • http://stackoverflow.com/questions/17156746/update-android-gallery/17159837#17159837 – Karthik Balakrishnan Jun 19 '13 at 04:03
  • You should `.close()` all your output streams in `finally` blocks. There are at least two places here where failing to write the fle will cause a file descriptor leak. – fge Jun 19 '13 at 04:09
  • I did both of these suggestions and the empty image is still left showing in the gallery. – Will Jamieson Jun 20 '13 at 12:59
  • @WillJamieson Probably a faulty thumbnail, delete the `.thumbnails` folder, `Android` will regenerate it anyway. – Karthik Balakrishnan Jun 20 '13 at 14:24
  • thats not it either, because when I look at my phones files the file is still there it just cannot open. As if it is a corrupted jpeg – Will Jamieson Jun 23 '13 at 02:39
  • 1
    To notify the gallery that the specific image was changed (deleted), instead of re-scanning the whole directory, see http://stackoverflow.com/questions/15837485/how-can-i-update-the-android-gallery-after-a-photo It sounds like you're having a problem deleting the file, though, so this probably won't entirely solve your issue. – GreyBeardedGeek Jun 23 '13 at 03:07

2 Answers2

12

This isn't a direct answer to your specific question, but I'd like to propose a different work flow that may avoid the problem entirely.

When you first take the picture, either keep it in memory (use BitmapFactory.decodeByteArray instead of BitmapFactory.decodeFile), or write the file to a temp file (see File.createTempFile). In either case, the idea is to not write the file to the gallery's directory.

Then, if and when the user chooses 'save', write/copy the file to the to the gallery's directory. If they choose 'delete', delete the temp file (or don't, and let the OS clean it up).

Once you write the file (save), update the gallery with the one specific file using

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(myNewFile)));

as mentioned in How can I update the Android Gallery after a photo?

Community
  • 1
  • 1
GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67
  • I was chosing not to keep the photo in memory because I was getting OOM errors I will try this though it seems like it should solve the problem – Will Jamieson Jun 23 '13 at 03:28
  • This is great, I'm using this to create a Temp file for each picture request, then store the resulting File in a variable so I can access it in the OnActivityResult. If the picture is cancelled and the requestCode is not RESULT_OK, I call temp.delete(). – G_V Dec 15 '14 at 09:14
0

This worked for me!! It is kotlin solution

 private fun DeleteImage(path: String) {
`val fullPathToFile = path
                activity!!.contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                MediaStore.Images.Media.DATA + "=?", arrayOf(fullPathToFile))}

`