【问题标题】:can't delete file from external storage in android programmatically无法以编程方式从android中的外部存储中删除文件
【发布时间】:2017-12-28 10:56:03
【问题描述】:

我正在尝试删除位于路径中的文件

/storage/714D-160A/Xender/image/Screenshot_commando.png

到目前为止我做了什么:

  try{
        String d_path = "/storage/714D-160A/Xender/image/Screenshot_commando.png";
        File file = new File(d_path);
        file.delete();

     }catch(Exception e){

        e.printStackTrace();
     }

文件还在原处(未删除:()

我也已在 Manifest 文件中授予权限。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.STORAGE" />

【问题讨论】:

  • 您遇到什么错误?添加您的 logcat 详细信息。
  • 如果您在搭载 Android M 或更高版本的设备上进行测试,则需要运行时权限。
  • 我在装有 android M 的设备上测试
  • 在 log-cat 中不显示任何错误,文件仍在其位置
  • 您是否以编程方式请求权限?

标签: java android file directory delete-directory


【解决方案1】:

使用Environment.getExternalStorageDirectory().getAbsolutePath()代替硬编码存储路径

String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
File f = new File(baseDir + "/714D-160A/Xender/image/Screenshot_commando.png");
boolean d = f.delete();

【讨论】:

  • 感谢您的回答,但我想删除外部存储(存储卡)文件。布尔返回 false,文件仍在原处(未删除)..
  • @Secret 你测试了Environment.getExternalStorageDirectory().getAbsolutePath() 而不是/storage 吗?
  • @Secret 我很确定问题出在文件地址上。测试位于外部存储根目录中的另一个文件
  • @Secret,您好我也在寻找能够从外部存储卡(物理安装内存)中删除文件的方法,您有解决方案吗?请帮帮我..
  • @BhaveshMoradiya 您需要ExternalStoragePermission,然后只需为您的文件调用File.delete()
【解决方案2】:
public static boolean delete(final Context context, final File file) {
    final String where = MediaStore.MediaColumns.DATA + "=?";
    final String[] selectionArgs = new String[] {
            file.getAbsolutePath()
    };
    final ContentResolver contentResolver = context.getContentResolver();
    final Uri filesUri = MediaStore.Files.getContentUri("external");

    contentResolver.delete(filesUri, where, selectionArgs);

    if (file.exists()) {

        contentResolver.delete(filesUri, where, selectionArgs);
    }
    return !file.exists();
}

【讨论】:

  • 此方法是否适用于运行 Android 5.0 及更高版本的 Android 设备?
  • 不,它在 Android 5.0 上不起作用,会导致很多问题。事实上,在sd-card 上编辑文件并不是那么容易,但它是可行的。看我的回答。
  • hii @Secret 一个建议 一个好的答案总是会解释所做的事情以及为什么以这种方式完成,不仅对于 OP,而且对于 SO 的未来访问者。所以如果可能的话,请用几句话编辑和解释:)
  • getContentUri("external") 中的“external”是什么? - @秘密
【解决方案3】:

使用ContentResolver删除媒体文件是错误的,会给用户带来很多问题。
在高于 Jelly Bean(4.3) 的 Android 版本上,您不能仅通过从 ContentResolver 中删除其信息来删除 sd-card 上的文件。
它仅适用于 KitKat(4.4) 之前的 Android 版本。
这就是 Android 团队提供DocumentProvider 的原因。

为什么contentResolver.delete(...) 错了?
1.填写sd-card
当您尝试在高于 4.3 的 Android 版本上通过ContentResolver 删除sd-card 上的媒体文件时,实际媒体文件将保持不变,因为contentResolver.delete(...) 方法仅删除信息(名称、日期、路径.. .) 媒体,您最终将在您的sd-card 上拥有未注册的媒体文件,ContentResolver 不再知道它们的存在,这就是为什么您无法在您的画廊中看到它们并且您认为它们已被删除使用这种方法,当他们还在那里时,每次用户尝试删除sd-card 上的媒体文件时填写sd-card

2。媒体文件(图片、视频、GIF ...)将返回图库
那里有许多应用程序,尤其是图库和文件管理器,它们会找到这些未注册的媒体文件,并按照正常行为将它们再次添加到ContentResolver,而用户认为他/她不需要的媒体文件已经消失。 当然,没有用户希望他/她假设已删除的图像或视频出现在演示中间。

那么,删除sd-card 上的媒体文件的正确方法是什么?
嗯,这个问题已经用DocumentProvider 回答了here

【讨论】:

  • 最初的问题甚至从未提到 ContentResolver。为什么你的答案集中在它上面?哦。我知道了。接受的答案使用 contentresolver。
  • The original question never even mentioned ContentResolver. Why does your answer focus on it? OH. I see. the accepted answer uses contentresolver. @Neo42 不。你的假设是错误的和不合逻辑的。我已经回答了解释如何以正确方式使用ContentResolver 的问题,几乎是在接受的答案出现并谈论ContentResolver 这是错误和不负责任的一年之前。这是我的答案中也提供的链接>>stackoverflow.com/a/39104124/2123400
【解决方案4】:

从 Android 4.4 开始,您无法使用正常方式写入 SD 卡文件(App 目录中的文件除外)。为此,您必须使用使用 DocumentFile 的存储访问框架。

以下代码适用于我:

private void deletefile(Uri uri, String filename) {
    DocumentFile pickedDir = DocumentFile.fromTreeUri(this, uri);

    DocumentFile file = pickedDir.findFile(filename);
    if(file.delete())
        Log.d("Log ID", "Delete successful");
    else
        Log.d("Log ID", "Delete unsuccessful");
}

其中filename是要删除的文件名,uriACTION_OPEN_DOCUMENT_TREE返回的URI:

private static final int LOCATION_REQUEST = 1;

private void choosePath() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    intent.addCategory(Intent.CATEGORY_DEFAULT);
    startActivityForResult(intent, LOCATION_REQUEST);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    if (requestCode == LOCATION_REQUEST && resultCode == Activity.RESULT_OK) {
        if (resultData != null) {
            Uri uri = resultData.getData();
            if (uri != null) {
                /* Got the path uri */
            }
        }
    }
}

【讨论】:

  • 在这个“private void deletefile(Uri uri, String filename)”中也需要文件名,但是如何从活动结果中的uri获取文件名...
  • @BhaveshMoradiya 抱歉回复晚了,我有点忙。我使用以下内容从 URI 获取路径:String path = FileUtil.getFullPathFromTreeUri(uri, this);FileUtil 类可以在这里找到:stackoverflow.com/a/36162691/3049655
  • @BhaveshMoradiya 您通过ACTION_OPEN_DOCUMENT_TREE 获得的URI 不是一个特定的文件,而是一个位置。如果您希望用户选择特定文件,则需要使用 ACTION_OPEN_DOCUMENT
  • DocumentFile 文件=pickDir.findFile(filename);出于某种原因返回 npe?
  • 找到了原因,我必须选择文件所在的文件夹;但是我怎样才能自动打开该文件夹,这样用户就不必浏览该文件夹了?
猜你喜欢
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
相关资源
最近更新 更多