Android 12 删除图像文件不起作用

发布于 2025-01-13 20:56:34 字数 3823 浏览 4 评论 0原文

对于 android 12,我无法删除应用程序创建的图像文件。方法 File.delete() 被忽略,我没有收到错误,但文件在它之后仍然存在。

图像文件是通过按“添加照片按钮”创建的,第一次按下后将调用此方法:

 private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    try {
        File photoFile = createImageFile();

        if (photoFile != null) {
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
            startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
        }
    }catch (Exception e){
        Log.i("ERROR",e.getMessage());
    }
}

创建图像文件方法:

private File createImageFile() {
    String imageFileName = String.format(new Locale("pl"), PHOTO_FILE_FORMAT, currentMonth.getMonth(), currentMonth.getYear());
    File storageDir = new File(ShiftCalendarApplication.PHOTO_DIRECTORY);

    if (!storageDir.exists()) {
        if(!storageDir.mkdirs())
            return null;
    }

    return new File(ShiftCalendarApplication.PHOTO_DIRECTORY, imageFileName + FILE_EXTENSION);
}

照片目录:

   public static final String PHOTO_DIRECTORY = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath() + "/My App/" + "Zdjecia/";

按另一个调用此方法的按钮删除文件,当用户在询问时选择“是”删除。

    private void deleteSelectedImage() {
    if (photos.get(monthsFromToday) != null) {
        AlertDialog.Builder builder = new AlertDialog.Builder(PhotoOfScheduleActivity.this);
        builder.setTitle("Usuń zdjęcie")
                .setIcon(android.R.drawable.ic_dialog_alert)
                .setMessage("Czy na pewno usunąć?")
                .setPositiveButton("Usuń", (dialog, which) -> {
                    File file = new File(paths.get(monthsFromToday));

                    Log.d("SAVED_IMAGE", "(BEFORE)FILE EXIST: " + file.exists());
                    file.delete();
                    Log.d("SAVED_IMAGE", "(AFTER)FILE EXIST: " + file.exists()); // FILE STILL EXIST HERE

                    reloadDrawables();
                    adapter = new SchedulePhotosPagerAdapter();
                    viewPager.setAdapter(adapter);
                    viewPager.setCurrentItem(monthsFromToday);
                })
                .setCancelable(true)
                .setNegativeButton("Anuluj", null)
                .show();
    }
}

重新加载存储照片路径的 Drawabled 方法:

    private void reloadDrawables() {
    File directory = new File(ShiftCalendarApplication.PHOTO_DIRECTORY);
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    photos = new SparseArray<>();
    paths = new SparseArray<>();
    int year = currentMonth.getYear();
    int month = currentMonth.getMonth();
    File[] files = directory.listFiles();

    if (directory.listFiles() != null) {
        for (File file : files) {
            if (file.isFile() && file.getName().endsWith(FILE_EXTENSION)) {
                try {
                    Photo photo = new Photo(removeExtension(file.getName()), file.getPath());
                    String[] date = photo.getPhotoName().split("-");
                    int pYear = Integer.parseInt(date[1]);
                    int pMonth = Integer.parseInt(date[0]);
                    int key = monthsFromToday;
                    key += (pYear - year) * 12;
                    key += pMonth - month;
                    paths.put(key, file.getPath());
                    photos.put(key, photo);
                } catch (Throwable e) {
                    Log.e(TAG, e.getMessage());
                }
            }
        }
    }
    if (adapter != null) {
        adapter.notifyDataSetChanged();
    }
}

File.delete() 不适用于 android >在本例中为 29

For android 12 i cannot remove image file created by app. Method File.delete() is ignored, i don't get error but file still exist after it.

Image file is created by press "Add photo button", after pressing at first this method is invoked:

 private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    try {
        File photoFile = createImageFile();

        if (photoFile != null) {
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
            startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
        }
    }catch (Exception e){
        Log.i("ERROR",e.getMessage());
    }
}

Create image file method:

private File createImageFile() {
    String imageFileName = String.format(new Locale("pl"), PHOTO_FILE_FORMAT, currentMonth.getMonth(), currentMonth.getYear());
    File storageDir = new File(ShiftCalendarApplication.PHOTO_DIRECTORY);

    if (!storageDir.exists()) {
        if(!storageDir.mkdirs())
            return null;
    }

    return new File(ShiftCalendarApplication.PHOTO_DIRECTORY, imageFileName + FILE_EXTENSION);
}

Photo directory:

   public static final String PHOTO_DIRECTORY = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath() + "/My App/" + "Zdjecia/";

File is delete by pressing another button which invoke this method is user select "yes" when is asked about deletion.

    private void deleteSelectedImage() {
    if (photos.get(monthsFromToday) != null) {
        AlertDialog.Builder builder = new AlertDialog.Builder(PhotoOfScheduleActivity.this);
        builder.setTitle("Usuń zdjęcie")
                .setIcon(android.R.drawable.ic_dialog_alert)
                .setMessage("Czy na pewno usunąć?")
                .setPositiveButton("Usuń", (dialog, which) -> {
                    File file = new File(paths.get(monthsFromToday));

                    Log.d("SAVED_IMAGE", "(BEFORE)FILE EXIST: " + file.exists());
                    file.delete();
                    Log.d("SAVED_IMAGE", "(AFTER)FILE EXIST: " + file.exists()); // FILE STILL EXIST HERE

                    reloadDrawables();
                    adapter = new SchedulePhotosPagerAdapter();
                    viewPager.setAdapter(adapter);
                    viewPager.setCurrentItem(monthsFromToday);
                })
                .setCancelable(true)
                .setNegativeButton("Anuluj", null)
                .show();
    }
}

Reload Drawabled method which store paths for photos:

    private void reloadDrawables() {
    File directory = new File(ShiftCalendarApplication.PHOTO_DIRECTORY);
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    photos = new SparseArray<>();
    paths = new SparseArray<>();
    int year = currentMonth.getYear();
    int month = currentMonth.getMonth();
    File[] files = directory.listFiles();

    if (directory.listFiles() != null) {
        for (File file : files) {
            if (file.isFile() && file.getName().endsWith(FILE_EXTENSION)) {
                try {
                    Photo photo = new Photo(removeExtension(file.getName()), file.getPath());
                    String[] date = photo.getPhotoName().split("-");
                    int pYear = Integer.parseInt(date[1]);
                    int pMonth = Integer.parseInt(date[0]);
                    int key = monthsFromToday;
                    key += (pYear - year) * 12;
                    key += pMonth - month;
                    paths.put(key, file.getPath());
                    photos.put(key, photo);
                } catch (Throwable e) {
                    Log.e(TAG, e.getMessage());
                }
            }
        }
    }
    if (adapter != null) {
        adapter.notifyDataSetChanged();
    }
}

File.delete() not working for for android > 29 in this case

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

居里长安 2025-01-20 20:56:34

着眼于 API 29,有很多 非-SDK接口已停止工作。 java.io.file 是受影响的文件之一,因此它不再起作用。

这就是我解决问题的方法:

import android.content.ContentResolver
import java.io.File

//'file' is the instance of your java.io.File
//'app' is your app context.

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){
    file.delete()
}else{
    val resolver = app.contentResolver
    resolver.delete(file.toUri(), null, null)
}

Staring on API 29, there a are a lot of non-SDK interfaces that have stopped working. java.io.file is one of the affected ones so it's no longer functional.

This is how I solved the issue:

import android.content.ContentResolver
import java.io.File

//'file' is the instance of your java.io.File
//'app' is your app context.

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){
    file.delete()
}else{
    val resolver = app.contentResolver
    resolver.delete(file.toUri(), null, null)
}
墨洒年华 2025-01-20 20:56:34

从 Android 11 及更高版本开始
从外部或内部存储中删除文件。
公共或私人路径。
使用MediaStore删除文件

这个答案用于删除任何媒体文件。(稍作修改)
https://stackoverflow.com/a/75640130/14035342

您可以使用相同的代码答案
只需将答案链接中的此方法更改为这样

private Uri get_Files_media_uri() {
        //MediaStore.Audio.Media.. or MediaStore.Video.Media... is same value value uri but title permission dialog deference as Audio or video
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
            return MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
        else
            return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    }

from Android 11 an higher
to delete file from external or internal Storage.
public or private path.
use MediaStore to Delete Files.

this Answer for delete any Media File.(With a slight modification)
https://stackoverflow.com/a/75640130/14035342

you can use same code Answer.
only Change this method in the answer link to like this

private Uri get_Files_media_uri() {
        //MediaStore.Audio.Media.. or MediaStore.Video.Media... is same value value uri but title permission dialog deference as Audio or video
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
            return MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
        else
            return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文