Android SAF(存储访问框架):从TreeUri获取特定文件Uri

时间:2016-08-20 13:03:29

标签: android file-io android-sdcard storage-access-framework

我正在使用外部SD卡的PersistableUriPermission并将其存储以供进一步使用。 现在我希望当用户向我提供文件路径时,从我的应用程序中的文件列表中,我想编辑文档并重命名。

所以我有要编辑的文件的文件路径。

我的问题是如何从我的TreeUri获取该文件的Uri以及编辑文件。

1 个答案:

答案 0 :(得分:11)

访问Sd-Card的文件

使用DOCUMENT_TREE对话框获取sd-card' Uri

告知用户如何在对话框中选择sd-card。 (带图片或gif动画)

// call for document tree dialog
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);

onActivityResult上,您将拥有所选目录Uri。 (sdCardUri)

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_CODE_OPEN_DOCUMENT_TREE:
            if (resultCode == Activity.RESULT_OK) {
                sdCardUri = data.getData();
             }
             break;
     }
  }

现在必须检查用户是否

一个。选择了SD卡

湾选择我们的文件所在的SD卡(某些设备可能有多个SD卡)。

我们通过层次结构查找文件来检查a和b,从sd root到我们的文件。如果找到文件,则获取a和b条件。

//First we get `DocumentFile` from the `TreeUri` which in our case is `sdCardUri`.
DocumentFile documentFile = DocumentFile.fromTreeUri(this, sdCardUri);

//Then we split file path into array of strings.
//ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "myImage.jpg"}
// There is a reason for having two similar names "MyFolder" in 
//my exmple file path to show you similarity in names in a path will not 
//distract our hiarchy search that is provided below.
String[] parts = (file.getPath()).split("\\/");

// findFile method will search documentFile for the first file 
// with the expected `DisplayName`

// We skip first three items because we are already on it.(sdCardUri = /storage/extSdCard)
for (int i = 3; i < parts.length; i++) {
    if (documentFile != null) {
        documentFile = documentFile.findFile(parts[i]);
    }
  }

if (documentFile == null) {

    // File not found on tree search
    // User selected a wrong directory as the sd-card
    // Here must inform user about how to get the correct sd-card
    // and invoke file chooser dialog again.

 } else {

    // File found on sd-card and it is a correct sd-card directory
    // save this path as a root for sd-card on your database(SQLite, XML, txt,...)

    // Now do whatever you like to do with documentFile.
    // Here I do deletion to provide an example.


    if (documentFile.delete()) {// if delete file succeed 
        // Remove information related to your media from ContentResolver,
        // which documentFile.delete() didn't do the trick for me. 
        // Must do it otherwise you will end up with showing an empty
        // ImageView if you are getting your URLs from MediaStore.
        // 
        Uri mediaContentUri = ContentUris.withAppendedId(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                longMediaId);
        getContentResolver().delete(mediaContentUri , null, null);
    }


 }

注意:

您必须为清单中的外部存储提供访问权限,并为应用内的os&gt; = Marshmallow提供访问权限。 https://stackoverflow.com/a/32175771/2123400

修改SD卡的文件

要编辑SD卡上的现有图像,如果您想调用其他应用为您执行此操作,则不需要执行上述任何步骤。

这里我们调用所有活动(来自所有已安装的应用程序)并具有编辑图像的功能。 (程序员在清单中标记他们的应用程序,以便提供其他应用程序(活动)的可访问性)。

在您的editButton点击事件:

String mimeType = getMimeTypeFromMediaContentUri(mediaContentUri);
startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_EDIT).setDataAndType(mediaContentUri, mimeType).putExtra(Intent.EXTRA_STREAM, mediaContentUri).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION), "Edit"), REQUEST_CODE_SHARE_EDIT_SET_AS_INTENT);

这就是如何获取mimeType:

public String getMimeTypeFromMediaContentUri(Uri uri) {
    String mimeType;
    if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
        ContentResolver cr = getContentResolver();
        mimeType = cr.getType(uri);
    } else {
        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
                .toString());
        mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                fileExtension.toLowerCase());
    }
    return mimeType;
}

注意:

在Android KitKat(4.4)上,请勿让用户选择SD卡,因为此版本的Android DocumentProvider不适用,因此我们没有机会访问sd-用这种方法卡。 查看DocumentProvider的API级别 https://developer.android.com/reference/android/provider/DocumentsProvider.html
我无法找到适用于Android KitKat(4.4)的任何内容。如果您发现有任何与KitKat有用的内容,请与我们分享。

在以下版本中,操作系统已提供对KitKat的访问权限。