Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get path from Uri

I am making the User selects a Storage either Internal or External Storage(SD Card) using the Storage Access Framework Document.

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

This is how I am trying to achieve this and this is what I have achieved till now-

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

And this is my 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;
        }
    }


}

So basically onActivityResult I am checking if the treeuri of the selected directory path is equal or not to the path required by me.

This is the treeuri for the selected directory content://com.android.externalstorage.documents/tree/primary%3A

This is the path which is being returned from the above treeuri /storage/sdcard0

The path which is expected to be returned is /storage/sdcard1.

So even after choosing the right directory the wrong path is being returned.

Can anyone help me to find the exact path of the treeuri or Can anyone help me to check if the treeuri belongs to Internal Storage or External Storage (SD Card).

like image 427
Rahulrr2602 Avatar asked Jan 26 '18 12:01

Rahulrr2602


People also ask

How do you find the absolute path of URI?

Uri uri = data. getData(); File file = new File(uri. getPath());//create path from uri final String[] split = file. getPath().

How do I get real path from Fileprovider URI?

You can try this solution for get real path from file provider URI. First you need to define file provider path file as following. Declare file provider in AndroidMenifest. xml as following.

How to get uri in java?

In general, an URI (Uniform Resource Identifier) represents a resource. The URI class of Java represents this format You can get the URI format of a file by invoking the toURI() method.

How to convert uri to file path in Android?

Uri object which is named uri and created exactly as in the question, uri. toString() returns a String in the format "file:///mnt/sdcard/myPicture.jpg" , whereas uri. getPath() returns a String in the format "/mnt/sdcard/myPicture.


1 Answers

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

You are welcome to use getParentFile() on DocumentFile, and see what it returns for the top of the document tree. They do not document exactly what happens here, but it should either return null or throw some sort of exception. You could then use that to determine whether the returned document tree happens to be a root of something.

However, there is no requirement that the "something" be external storage or removable storage. The user could choose a document tree from Google Drive, or a Windows file server, or any number of other data sources. There is no requirement that you be able to identify where the data source comes from.

And this is my FileUtil class

Much of the code in that class makes invalid assumptions. The rest uses reflection, and it is quite possible that 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

There is no "exact path of the treeuri".

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

That is not possible in general.

like image 170
CommonsWare Avatar answered Sep 29 '22 16:09

CommonsWare