对于 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
从 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)
}
从 Android 11 到更高版本 从外部或内部存储中删除文件。 公共或私人路径。 使用MediaStore删除文件.
此答案用于删除任何媒体文件。(稍作修改) https://stackoverflow.com/a/75640130/14035342
您可以使用相同的代码Answer。 仅将答案链接中的此方法更改为喜欢此
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;
}