【问题标题】:How to get a DocumentContract using Android Storage Access Framework如何使用 Android 存储访问框架获取 DocumentContract
【发布时间】:2017-08-21 15:30:15
【问题描述】:

我正在尝试在我的应用中实现 SAF。我已经设法使用以下方法将音乐文件复制到外部 SD 卡:

         Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, REQUEST_CODE_OPEN_DIRECTORY);

打开文件/文件夹选择器

复制:

   private String copyFile(String inputPath, String inputFile, Uri treeUri) {
    InputStream in = null;
    OutputStream out = null;
    String error = null;
    DocumentFile pickedDir = DocumentFile.fromTreeUri(getActivity(), treeUri);
    String extension = inputFile.substring(inputFile.lastIndexOf(".")+1,inputFile.length());

    try {
        DocumentFile newFile = pickedDir.createFile("audio/"+extension, inputFile);
        out = getActivity().getContentResolver().openOutputStream(newFile.getUri());
        in = new FileInputStream(inputPath + inputFile);

        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        in.close();
        // write the output file (You have now copied the file)
        out.flush();
        out.close();

    } catch (FileNotFoundException fnfe1) {
        error = fnfe1.getMessage();
    } catch (Exception e) {
        error = e.getMessage();
    }
    return error;
}

但是 当用户选择“移动”时,我想删除可能不在文档树中的原始位置中的文件,因为它们与选择的文件夹无关。它们的路径取自 Mediastore_DATA 字段。 问题是如何获得包含这些文件的 DocumentContract 以便删除它们?

【问题讨论】:

  • 为什么需要 DocumentsContract?您可以使用 File 类删除它们,因为您拥有用于 FileInputStream 的完整路径。
  • which brings up the File/folder Picker。不可以。那时您只能选择一个文件夹。一颗树。没有文件。
  • Their paths are taken from the Mediastore_DATA field.。为什么?。您只展示了如何选择目标目录。但是您没有告诉用户如何选择必须复制/移动的音乐文件。我想你也应该这么说。
  • @greenaps,需要一个合同,因为删除可能发生在外部 sdcard 上。我只对选择“复制到文件夹”感兴趣。音乐文件是播放列表中的条目,因此可以存在于内部或外部存储器中。整个想法是将播放列表上的曲目复制或移动到新文件夹中,在移动的情况下,随后删除原件。
  • 你还没有回复我的Why?。或提供解决您的问题所需的更多信息。

标签: android file-permissions storage-access-framework


【解决方案1】:

如果不调用另一个 UI,则无法从 SAF 获得 URI 许可。

由于您使用 MediaStore 获取媒体文件,您可以使用 ContentResolver.delete() 和您必须删除的媒体 URI。我假设你有 WRITE_EXTERNAL_STORAGE 权限。我不建议使用 File 直接删除底层文件,因为 MediaStore 没有机会清理它。

或者,您也可以尝试https://developer.android.com/reference/android/os/storage/StorageVolume.html#createAccessIntent(java.lang.String) 来获取整个主存储的树 URI 权限。但是它仅适用于 API 24。

【讨论】:

  • ttanxu,谢谢你回答了我的问题。我确实尝试使用 new File(fullpath_from_Mediastore_DATA).delete();方法,但外部 SD 卡上没有任何内容被删除。我希望能够获得文档树(使用 ACTION_OPEN_DOCUMENT_TREE 的一次性意图,将结果写入首选项),然后将每个轨道附加到 documentTree uri.while 枚举树的孩子。我以 Github 的 LocalStorage 应用为例
  • 您提供的链接看起来很有希望
  • 您已经从 MediaStore 获得了_data 列,如果您持有 WRITE_EXTERNAL_STORAGE_PERMISSION,您应该可以调用 mContext.getContentResolver().delete(MediaStore.Files.getContentUri("external"), "lower(_data) = lower(?)", new String[] { path_from_MediaStore_DATA }); 从 MediaStore 和磁盘中删除该项目。
  • 上述内容只会从 Mediastore 中删除轨道条目。它不会删除实际文件。 WRITE_EXTERNAL 等在清单中,但重点是 file.delete 不起作用,所以我回到第 1 格。我认为这就是谷歌提出 StorageVolume 的原因。他们引入“安全性”的方法对我来说有点随意。谢谢您的帮助。我将检查 StorageVolume 方法。
猜你喜欢
  • 2021-10-14
  • 1970-01-01
  • 2015-06-28
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 2016-10-14
相关资源
最近更新 更多