Reputation: 18501
Suppose a Uri can be either of the following:
It refers to a file under a directory in both situations.
Is there a straightforward way to get its parent directory's Uri without trying each of the two to see which one works?
[Edit]: Here is an example for SAF:
Uri:
content://com.android.externalstorage.documents/tree/0000-0000%3Atest/document/0000-0000%3Atest%2Ffoo%2FMovies%2FRR%20parking%20lot%20a%202018_02_22_075101.mp4
getPath():
/tree/0000-0000:test/document/0000-0000:test/foo/Movies/RR parking lot a 2018_02_22_075101.mp4
getPathSegments():
0 = "tree"
1 = "0000-0000:test"
2 = "document"
3 = "0000-0000:test/foo/Movies/RR parking lot a 2018_02_22_075101.mp4"
The parent folder should be test/foo/Movies.
Here is an example for a regular file:
Uri:
file:///storage/emulated/0/foo/Movies/RR%20parking%20lot%20a%202018_02_22_081351.mp4
getPath():
/storage/emulated/0/foo/Movies/RR parking lot a 2018_02_22_081351.mp4
getPathSegments():
0 = "storage"
1 = "emulated"
2 = "0"
3 = "foo"
4 = "Movies"
5 = "RR parking lot a 2018_02_22_081351.mp4"
Upvotes: 6
Views: 2061
Reputation: 711
3 years late, I had a similar problem. I've resolved it using the Android 26 API DocumentsContract.findDocumentPath. It's OK for me since I use File API on earlier Android versions in my project.
Essentially, I find the document's path using findDocumentPath and remove the last segment from it (i.e. find the parent directory's path). Then, to reform the SAF Uri, I find the last / or : character in the Uri and replace the next part with parent directory's path.
public static String GetParentDirectory( ContentResolver resolver, String rawUri )
{
if( !rawUri.contains( "://" ) )
{
// This is a raw filepath, not a SAF path
return new File( rawUri ).getParent();
}
// Calculate the URI's path using findDocumentPath, omit the last path segment from it and then replace the rawUri's path component entirely
DocumentsContract.Path rawUriPath = DocumentsContract.findDocumentPath( resolver, Uri.parse( rawUri ) );
if( rawUriPath != null )
{
List<String> pathSegments = rawUriPath.getPath();
if( pathSegments != null && pathSegments.size() > 0 )
{
String rawUriParentPath;
if( pathSegments.size() > 1 )
rawUriParentPath = Uri.encode( pathSegments.get( pathSegments.size() - 2 ) );
else
{
String fullPath = pathSegments.get( 0 );
int separatorIndex = Math.max( fullPath.lastIndexOf( '/' ), fullPath.lastIndexOf( ':' ) + 1 );
rawUriParentPath = separatorIndex > 0 ? Uri.encode( fullPath.substring( 0, separatorIndex ) ) : null;
}
if( rawUriParentPath != null && rawUriParentPath.length() > 0 )
{
int rawUriLastPathSegmentIndex = rawUri.lastIndexOf( '/' ) + 1;
if( rawUriLastPathSegmentIndex > 0 )
{
String rawUriParent = rawUri.substring( 0, rawUriLastPathSegmentIndex ) + rawUriParentPath;
if( !rawUriParent.equals( rawUri ) )
return rawUriParent;
}
}
}
}
return null;
}
Upvotes: 2