java - 从 Uri 获取路径

标签 java android file uri storage-access-framework

我正在让用户使用存储访问框架文档选择内部存储或外部存储(SD 卡)。

在用户选择目录后,我想检查用户选择的目录是否属于特定存储(内部或外部存储)的根文件夹。

这就是我努力实现这一目标的方式,这就是我到目前为止所取得的成就-

public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode == RESULT_OK && requestCode == 42) {
            Uri treeUri = data.getData();
          if (!wrong_directory_selected(treeUri, Context)) {
               // Permission granted for the Directory as required by me

                } else {
                    // Permission not granted for the Directory as required by me
                }
            } 
        }
    }

public boolean wrong_directory_selected(Uri uri, Context con)
    {
        final File uri_path=new File(FileUtil.getFullPathFromTreeUri(uri,con.getApplicationContext()));
        if(uri_path!=null)
        {
            if(uri_path.getName().toLowerCase().equals(new File(PathForWhichPermissionNeeded).getName().toLowerCase()))
            {

                return false;
            }
        }

        return  true;
    }

这是我的 FileUtil 类-

public final class FileUtil {


    private static final String PRIMARY_VOLUME_NAME = "primary";




    @Nullable
    public static String getFullPathFromTreeUri(@Nullable final Uri treeUri, Context con)
    {

        if (treeUri == null)
        {
            return null;
        }
        String volumePath = getVolumePath(getVolumeIdFromTreeUri(treeUri),con);

        if (volumePath == null)
        {
            return File.separator;
        }
        if (volumePath.endsWith(File.separator))
        {
            volumePath = volumePath.substring(0, volumePath.length() - 1);

        }

        String documentPath = getDocumentPathFromTreeUri(treeUri);
        Log.e("DocumentPath",documentPath);
        if (documentPath.endsWith(File.separator))
        {
            documentPath = documentPath.substring(0, documentPath.length() - 1);

        }

        if (documentPath.length() > 0)
        {
            if (documentPath.startsWith(File.separator))
            {

                return volumePath + documentPath;
            }
            else {

                return volumePath + File.separator + documentPath;
            }
        }
        else
        {

            return volumePath;
        }
    }


    private static String getVolumePath(final String volumeId, Context con)
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
        {
            return null;
        }

        try {
            StorageManager mStorageManager =
                    (StorageManager) con.getSystemService(Context.STORAGE_SERVICE);

            Class<?> storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");

            Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
            Method getUuid = storageVolumeClazz.getMethod("getUuid");
            Method getPath = storageVolumeClazz.getMethod("getPath");
            Method isPrimary = storageVolumeClazz.getMethod("isPrimary");
            Object result = getVolumeList.invoke(mStorageManager);

            final int length = Array.getLength(result);
            for (int i = 0; i < length; i++)
            {
                Object storageVolumeElement = Array.get(result, i);
                String uuid = (String) getUuid.invoke(storageVolumeElement);
                Boolean primary = (Boolean) isPrimary.invoke(storageVolumeElement);

                // primary volume?
                if (primary && PRIMARY_VOLUME_NAME.equals(volumeId))
                {
                    return (String) getPath.invoke(storageVolumeElement);
                }

                // other volumes?
                if (uuid != null)
                {
                    if (uuid.equals(volumeId))
                    {
                        return (String) getPath.invoke(storageVolumeElement);
                    }
                }
            }

            // not found.
            return null;
        }
        catch (Exception ex)
        {
            return null;
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static String getVolumeIdFromTreeUri(final Uri treeUri)
    {
        final String docId = DocumentsContract.getTreeDocumentId(treeUri);
        final String[] split = docId.split(":");

        if (split.length > 0)
        {
            return split[0];
        }
        else
        {
            return null;
        }
    }


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static String getDocumentPathFromTreeUri(final Uri treeUri)
    {
        final String docId = DocumentsContract.getTreeDocumentId(treeUri);
        final String[] split = docId.split(":");
        if ((split.length >= 2) && (split[1] != null))
        {
            return split[1];
        }
        else
        {
            return File.separator;
        }
    }


}

所以基本上 onActivityResult 我正在检查所选目录路径的 treeuri 是否等于我需要的路径。

这是所选目录content://com.android.externalstorage.documents/tree/primary%3A

treeuri

这是从上面的 treeuri /storage/sdcard0 返回的路径

预期返回的路径是/storage/sdcard1

因此,即使选择了正确的目录,也会返回错误的路径。

谁能帮我找到treeuri的确切路径或者谁能帮我检查treeuri是属于内部存储还是外部存储(SD卡) .

最佳答案

I want to check if the Directory selected by the user is of the Root folder of the particular Storage( Internal or External Storage).

欢迎您对 DocumentFile 使用 getParentFile(),并查看它返回文档树顶部的内容。他们没有记录这里到底发生了什么,但它应该返回 null 或抛出某种异常。然后,您可以使用它来确定返回的文档树是否恰好是某物的根。

但是,没有要求“某物”是external storageremovable storage .用户可以从 Google Drive、Windows 文件服务器或任意数量的其他数据源中选择文档树。不要求您能够识别数据源的来源。

And this is my FileUtil class

该类中的许多代码都做出了无效的假设。其余的使用反射,很有可能 the next version of Android will ban access to hidden APIs using reflection .

Can anyone help me to find the exact path of the treeuri

没有“treeuri 的确切路径”。

Can anyone help me to check if the treeuri belongs to Internal Storage or External Storage (SD Card)

这在一般情况下是不可能的。

关于java - 从 Uri 获取路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48461317/

相关文章:

android - 让服务在后台运行而不显示通知

javascript - 使用 Prototype 或纯 Javascript 编写文件

java - try 和 catch 是否被视为 if 之后的一个语句?

android - 获取snackbar支持库的高度

在 ListView 中使用 ratingbar 的 android 必需示例

java - 尝试更新 src/web/prod 文件夹(jsp)中的文件

Java代码找不到或定位指定的文件路径

java - Java 中的随机游走

java - 将方法参数名称保留在字节码中,以便在使用 Maven 构建时可以通过反射使用它们

java - 如何maven jar-with-dependencies pom.xml 覆盖