You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 13下如何通过代码删除DCIM子文件夹中的照片?

问题:Android 13下无法删除DCIM子文件夹中的照片(结合FileProvider与相机Intent)

场景与问题

  • 运行环境:Android 13,仅使用内部存储,Manifest已配置读写权限,运行时仅申请了相机和读取图片权限
  • 目标路径:/storage/emulated/0/DCIM/NewCam/NewCamPhoto.jpg
  • 问题:使用FileProvider配合相机Intent保存照片时,仅当目标文件/文件夹不存在时才能正常保存;手动删除现有照片后相机可正常拍摄保存,但通过代码删除该位置的照片/文件夹无效,照片仍存在

现有代码

1. 删除文件夹的尝试代码

public static void deleteFolder(String folderPath) {
    Log.d("yoyo","**** SCANNER **** DELETING "+folderPath);
        File folder = new File(folderPath);
        if (folder.exists()) {
            String[] children = folder.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteRecursive(new File(folder, children[i]));
                if (!success) {
                    return;
                }
            }
            // The folder is now empty so delete it
            folder.delete();
        }
    }

    private static boolean deleteRecursive(File file) {
        if (file.isDirectory()) {
            String[] children = file.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteRecursive(new File(file, children[i]));
                if (!success) {
                    return false;
                }
            }
        } else {
            return file.delete();
        }
        return true;
    }

2. 相机Intent相关代码

Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photo = new File(path, Name); if (photo.exists()) photo.delete();
PhotoPath = photo.getAbsolutePath();
i.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(RunnerActivity.CurrentActivity, RunnerActivity.CurrentActivity.getPackageName() + ".NewCam",photo));
RunnerActivity.CurrentActivity.startActivityForResult(i, REQUEST_CODE_CAMERA);

3. Manifest中的FileProvider配置

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.cam.newcam.scannerprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

4. provider_paths.xml内容

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="." />

    <!-- Access to a specific subdirectory within DCIM -->
    <external-path name="external_dcim" path="DCIM/NewCam" />
</paths>

解决方案

1. 修正FileProvider Authorities匹配问题

代码中FileProvider.getUriForFile的第二个参数(authorities)必须与Manifest中配置的android:authorities完全一致。

将相机Intent代码中的authorities修改为Manifest中配置的值:

// 替换原来的authorities参数为Manifest中配置的"com.cam.newcam.scannerprovider"
i.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(RunnerActivity.CurrentActivity, 
        "com.cam.newcam.scannerprovider", photo));

2. 改用MediaStore API删除媒体文件

Android 13对DCIM等媒体目录的文件访问有严格限制,直接使用File.delete()可能因媒体库索引或权限问题无法生效,需通过MediaStore API删除:

private boolean deletePhotoFromMediaStore(Context context, String photoPath) {
    // 先尝试从MediaStore中查找并删除
    String[] projection = {MediaStore.Images.Media._ID};
    String selection = MediaStore.Images.Media.DATA + "=?";
    String[] selectionArgs = {photoPath};

    Cursor cursor = context.getContentResolver().query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            projection,
            selection,
            selectionArgs,
            null);

    if (cursor != null) {
        if (cursor.moveToFirst()) {
            long mediaId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
            Uri mediaUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediaId);
            int deletedRows = context.getContentResolver().delete(mediaUri, null, null);
            cursor.close();
            return deletedRows > 0;
        }
        cursor.close();
    }

    // 如果MediaStore中未找到,尝试直接删除文件
    File photoFile = new File(photoPath);
    return photoFile.delete();
}

3. 调整权限申请(Android 13)

Android 13删除媒体文件需要READ_MEDIA_IMAGES权限,需在Manifest中声明并运行时申请:

Manifest声明:

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

运行时申请代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (ContextCompat.checkSelfPermission(RunnerActivity.CurrentActivity, 
            Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
        // 使用ActivityResultAPI申请权限
        ActivityResultLauncher<String> requestPermissionLauncher = 
                RunnerActivity.CurrentActivity.registerForActivityResult(
                        new ActivityResultContracts.RequestPermission(),
                        isGranted -> {
                            if (isGranted) {
                                // 权限授予后执行删除和相机逻辑
                                launchCameraIntent();
                            } else {
                                // 提示用户需要权限才能删除照片
                            }
                        });
        requestPermissionLauncher.launch(Manifest.permission.READ_MEDIA_IMAGES);
        return;
    }
}
// 权限已授予,直接执行
launchCameraIntent();

4. 启动相机Intent前调用删除方法

修改相机启动逻辑,先调用删除方法:

private void launchCameraIntent() {
    Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    File photo = new File(path, Name);
    // 删除目标照片
    deletePhotoFromMediaStore(RunnerActivity.CurrentActivity, photo.getAbsolutePath());
    PhotoPath = photo.getAbsolutePath();
    // 使用正确的authorities获取FileProvider Uri
    i.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(RunnerActivity.CurrentActivity, 
            "com.cam.newcam.scannerprovider", photo));
    RunnerActivity.CurrentActivity.startActivityForResult(i, REQUEST_CODE_CAMERA);
}

补充说明

  • 如果需要删除整个DCIM/NewCam文件夹,需遍历文件夹内所有文件,逐个用MediaStore API删除,最后再调用folder.delete()删除空文件夹
  • Android 13中,APP删除自身创建的媒体文件也需通过MediaStore API,确保媒体库索引同步,避免出现文件已删除但系统相册仍显示的情况

内容的提问来源于stack exchange,提问作者rafhelp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 10:53:10