从 Uri 获取路径

Get path from Uri

我正在让用户使用存储访问框架文档选择内部存储或外部存储(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 class-

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是否等于我需要的路径。

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

这是从上面返回的路径 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(),并查看文档树顶部 return 的内容。他们没有记录这里到底发生了什么,但它应该 return null 或抛出某种异常。然后您可以使用它来确定 returned 文档树是否恰好是某物的根。

但是,不要求 "something" 必须是 external storage or removable storage。用户可以从 Google 驱动器、Windows 文件服务器或任意数量的其他数据源中选择文档树。不要求您能够识别数据源的来源。

And this is my FileUtil class

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

没有"exact path of the treeuri".

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

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

I want to check if the Directory selected by the user is of the Root folder of the particular Storage

这很简单。如果内容方案以 %3A 结束,则为

所以请检查 data.getData().toString()