Android SAF(存储访问框架):从TreeUri获取特定的文件Uri [英] Android SAF (Storage Access FrameWork): Get particular file Uri from TreeUri

查看:2494
本文介绍了Android SAF(存储访问框架):从TreeUri获取特定的文件Uri的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



我的问题是如何从我的TreeUri得到该文件的Uri作为编辑文件。访问Sd卡的文件





$ b

解决方案

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



通知用户如何在对话框中选择 sd-card 。 (含图片或GIF动画)

$ p $ //调用文档树对话框
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();
}
喙;


$ / code $ / pre

现在必须检查用户,

a。选择了SD卡

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

$ hr

a和b通过层次结构查找文件,从sd root到我们的文件。

  //首先我们从`TreeUri`中得到`DocumentFile`在我们的例子中是'sdCardUri`。 
DocumentFile documentFile = DocumentFile.fromTreeUri(this,sdCardUri);

//然后我们将文件路径分割成字符串数组。
// ex:parts:{,storage,extSdCard,MyFolder,MyFolder,myImage.jpg}
//有两个类似的原因在
中命名MyFolder//我的示例文件路径显示路径名称中的相似性不会
//分散我们在下面提供的喜好搜索。
String [] parts =(file.getPath())。split(\\ /);

// findFile方法将搜索documentFile中的第一个文件
//预期的`DisplayName`

//我们跳过前三项,因为我们已经(sdCardUri = / storage / extSdCard)
for(int i = 3; i< parts.length; i ++){
if(documentFile!= null){
documentFile = documentFile.findFile(份[I]);


$ b $ if(documentFile == null){

//在树搜索中找不到文件
//用户选择一个错误的目录作为SD卡
//这里必须通知用户如何获得正确的SD卡
//并再次调用文件选择器对话框。

} else {

//在sd-card上找到的文件,它是一个正确的sd-card目录
//将此路径保存为sd的根目录卡上的数据库(SQLite,XML,TXT,...)

//现在做任何你喜欢用documentFile做。
//这里我做删除来举个例子。

$ b $ if(documentFile.delete()){//如果删除文件成功
//从ContentResolver中删除与媒体相关的信息
//哪个文件.delete()没有为我做诡计。
//必须这样做,否则如果您从MediaStore获取您的URL,您将最终显示一个空的
// ImageView。
//
Uri mediaContentUri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
longMediaId);
getContentResolver()。delete(mediaContentUri,null,null);





$ b

注意:您必须为清单内的外部存储设备提供访问权限,并在应用程序内为os> =棉花糖提供访问权限。
https://stackoverflow.com/a/32175771/2123400





编辑SD卡的文件



你的SD卡你不需要任何上述步骤,如果你想调用另一个应用程序来为你做。



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



在editButton click事件中:

  String mimeType = getMimeTypeFromMediaContentUri(mediaContentUri); (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); 
startActivityForResult(Intent.createChooser)

这是如何获得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($ b $ fileExtension.toLowerCase());
}
返回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以下版本的sd-card。


I am taking External Sd Card's PersistableUriPermission and storing it for further use. Now I want that when user provides me with the file path, from list of files in my application, I want to edit the document and rename it.

So I have the file path of the file to edit.

My question is how do I get that file's Uri from my TreeUri so as edit file.

解决方案

Access Sd-Card's files

Use DOCUMENT_TREE dialog to get sd-card's Uri.

Inform user about how to choose sd-card on the dialog. (with pictures or gif animations)

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

On onActivityResult you'll have the selected directory 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();
             }
             beak;
     }
  }

Now must check if the user,

a. selected the sd-card

b. selected the sd-card that our file is on (some devices could have multiple sd-cards).


We check both a and b by finding the file through the hierarchy, from sd root to our file. If file found, both of a and b conditions are acquired.

//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);
    }


 }

Note:

You must provide access permission to the external storage inside your manifest and for os>=Marshmallow inside the app. https://stackoverflow.com/a/32175771/2123400


Edit Sd-Card's Files

For editing an existing image on your sd-card you don't need any of above steps if you want to invoke another app to do it for you.

Here we invoke all the activities (from all the installed apps) with the capability of editing the images. (Programmers mark their apps in the manifest for its capabilities to provide accessibility from other apps (activities)).

on your editButton click event:

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);

and this is how to get 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;
}

Note:

On Android KitKat(4.4) don't ask the user to select the sd-card because on this version of Android DocumentProvideris not applicable, hence we have no chance to have access to the sd-card with this approach. Look at the API level for the DocumentProvider https://developer.android.com/reference/android/provider/DocumentsProvider.html
I couldn't find anything that works on Android KitKat(4.4). If you found anything useful with KitKat please share with us.

On versions below the KitKat access to sd-card is already provided by the OS.

这篇关于Android SAF(存储访问框架):从TreeUri获取特定的文件Uri的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆