安卓10 : How to delete MediaStore item and it's associated data on file system programmatically?

标签 android mediastore scoped-storage

我正在更新我的应用程序以使用 Android 10 中引入的 Scoped Storage 功能。

我的应用程序与 MediaStore 一起使用并显示图像、视频和音频文件,并为用户提供删除项目的能力。

我之前为删除文件所做的操作:

  • MediaStore.MediaColumns.DATA 获取路径
  • 二手 new File(path).delete()删除该文件
  • 手动更新 MediaStore

  • 现在 MediaStore.MediaColumns.DATA 不可用,我迁移到使用 ContentResolver.delete() 从 MediaStore 中删除项目

    例如,我有该项目的 uri:content://media/external/images/media/502 (它的有效uri,我在网格中显示它的缩略图)。我是否在 MediaStore 或其他应用程序中插入了这个项目并不重要。

    我用 context.getContentResolver().delete(uri, null, null) .它要么成功删除(返回 1 行),要么捕获 RecoverableSecurityException使用 startIntentSenderForResult()访问当前 uri,然后使用相同的 getContentResolver().delete()onActivityResult() 中删除它和 然后 成功删除。

    无论哪种方式,该项目都会从 MediaStore 中删除,并且在我查询 MediaStore 以获取图像时或在其他应用程序中都不会显示在结果中。

    但是 此文件存在于文件系统中(使用 SAF 和各种文件管理器(Google Files、Total Commander)检查)

    有时(取决于 Android 版本和媒体类型)这些项目是 手机重启后带回 MediaStore (或在打开 Google 相册后 - 它会扫描文件系统)

    例如:我的 Google Pixel 和 Google Pixel 3a XL 上的 Android 10 的行为与上述图像/视频/音频的行为相同,但小米 Mi A2 Lite 上的 Android 9 仅对音频文件的行为如此,而删除图像/视频则很好。

    我有 android:requestLegacyExternalStorage="false"在 list 中。

    有没有办法强制 MediaStore 也删除文件系统上的数据?为什么文件系统上的文件被遗忘了?

    最佳答案

    使用此函数使用文件的显示名称删除文件:
    此函数将删除 MediaStore 项目及其在 Android-10 或 Android-Q 文件系统上的关联数据
    注意:就我而言,我正在使用 MediaStore.Files.FileColumns 之类的文件。

    public static boolean deleteFileUsingDisplayName(Context context, String displayName) {
    
        Uri uri = getUriFromDisplayName(context, displayName);
        if (uri != null) {
            final ContentResolver resolver = context.getContentResolver();
            String[] selectionArgsPdf = new String[]{displayName};
    
            try {
                resolver.delete(uri, MediaStore.Files.FileColumns.DISPLAY_NAME + "=?", selectionArgsPdf);
                return true;
            } catch (Exception ex) {
                ex.printStackTrace();
                // show some alert message
            }
        }
        return false;
    
    }
    
    使用此函数从 DisplayName 获取 Uri
    public static Uri getUriFromDisplayName(Context context, String displayName) {
    
        String[] projection;
        projection = new String[]{MediaStore.Files.FileColumns._ID};
    
        // TODO This will break if we have no matching item in the MediaStore.
        Cursor cursor = context.getContentResolver().query(extUri, projection,
                MediaStore.Files.FileColumns.DISPLAY_NAME + " LIKE ?", new String[]{displayName}, null);
        assert cursor != null;
        cursor.moveToFirst();
    
        if (cursor.getCount() > 0) {
            int columnIndex = cursor.getColumnIndex(projection[0]);
            long fileId = cursor.getLong(columnIndex);
    
            cursor.close();
            return Uri.parse(extUri.toString() + "/" + fileId);
        } else {
            return null;
        }
    
    }
    

    关于安卓10 : How to delete MediaStore item and it's associated data on file system programmatically?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60702967/

    相关文章:

    java - 相机X : How to call the analyze method with an image

    Android MVP架构——repository和view之间的通信

    android - 在 Android Q 上使用 Glide 显示来自具有 "content://"方案的 URI 的图像

    Android:从android gallery app中选择后从mediaStore获取路径

    android - 将 PDF 保存在 Android 11 上的外部下载目录中

    java - 使用 Android 的 MediaStore(ContentResolver/范围存储)创建图像文件后文件扩展名和文件名错误

    android - 如何从1.82版本升级市场应用程序?

    滑动抽屉内的 Android 选项卡

    android - CursorAdapter 在 Android 上如何在 GridView 中工作

    android - 当应用程序目标为 (Android 11/API 30) 或更高版本时,如何将文件保存在 android 的根文件夹中?